#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <semaphore.h>
#include <pthread.h>
#include <time.h>
#include "tiposCache.h"
#include "tiposFileSystem.h"
#include "tiposSockets.h"
#include "tiposPaquetes.h"
#include "libFileSystem.h"
#include "libPaquetes.h"
#include "libSockets.h"
#include "libCache.h"
#include "utils.h"

#include "libFileSystem.h"

extern int8_t imprimirDebug;
extern int8_t usarFUSE;
extern int8_t usarSockets;
extern int8_t usarPoolConexiones;

extern uint32_t* tablaFatEnMem;
extern int8_t primeraLecturaFat;

extern t_fat32_bootSector bootSector;
extern pthread_mutex_t mutexUsandoFat;
extern pthread_mutex_t mutexUsandoCache;
extern pthread_mutex_t mutexUsandoPoolConexiones;

#define SECTORES_BLOQUE 8

//--------------------------------------------------
//MANEJO DE SECTORES
//--------------------------------------------------
int8_t leerBootSector(void) {
	if (imprimirDebug) {
		printf("--------------------leerBootSector--------------------\n");
	}

	char* contenido = (char*) malloc(TAMANIO_BLOQUE);
	int8_t error = leerBloque(0, contenido);
	if (!error) {
		memcpy(&bootSector, contenido, sizeof(t_fat32_bootSector));
		return 0;
	} else {
		return error;
	}

	/*FILE* fp;
	 fp = fopen("/home/utn_so/Escritorio/fat32.disk", "r");
	 char sector[512];
	 fread(sector, sizeof(char), 512, fp);
	 memcpy(&bootSector, sector, sizeof(t_fat32_bootSector));
	 fclose(fp);
	 return 0;*/

	/*int8_t error = 0;
	 int32_t descriptor;
	 printf("Voy a pedir el boot sector.\n");
	 int8_t recibiBootSector = 0;
	 while (!recibiBootSector && !error) {
	 pthread_mutex_lock(&mutexUsandoPoolConexiones);
	 error = obtenerConexion(&descriptor);
	 pthread_mutex_unlock(&mutexUsandoPoolConexiones);

	 if (!error) {

	 printf("Consegui una conexion disponible: [%d]\n", descriptor);

	 t_paquete_lectura paqueteLectura;
	 paqueteLectura.type = TIPO_LECTURA;
	 paqueteLectura.pLength = 1 * sizeof(uint64_t);
	 paqueteLectura.payLoad = (uint64_t*) malloc(paqueteLectura.pLength);
	 memset(paqueteLectura.payLoad, 0, paqueteLectura.pLength);
	 paqueteLectura.payLoad[0] = 0;

	 t_paquete paquete;
	 error = paqueteLecturaAPaquete(paqueteLectura, &paquete);

	 if (!error) {

	 printf("Envio el pedido de lectura del boot sector.\n");

	 error = enviarPaquete(paquete, descriptor);

	 if (!error) {

	 free(paquete.payLoad);

	 error = recibirPaquete(&paquete, descriptor);

	 if (!error) {

	 printf("Recibi un paquete.\n");

	 if (esPaqueteEscritura(paquete.type)) {

	 printf("El paquete es de tipo escritura.\n");

	 t_paquete_escritura paqueteEscritura;

	 error = paqueteAPaqueteEscritura(paquete, &paqueteEscritura);

	 if (!error) {

	 if ((paqueteEscritura.pLength == 520) && (paqueteEscritura.payLoad[0].numSector == 0)) {

	 printf("El paquete recibido es el boot sector.\n");

	 memcpy(&bootSector, paqueteEscritura.payLoad[0].contenidoSector, 512);

	 recibiBootSector = 1;

	 pthread_mutex_lock(&mutexUsandoPoolConexiones);
	 error = habilitarConexion(descriptor);
	 pthread_mutex_unlock(&mutexUsandoPoolConexiones);

	 if (!error) {
	 printf("Se volvio a habilitar la conexion\n");
	 }
	 } else {
	 //NO SE DEVOLVIO EL BOOT SECTOR
	 printf("Lo recibido no es el boot sector, vuelvo a hacer el pedido.\n");
	 recibiBootSector = 0;
	 }

	 } else
	 //HUBO UN ERROR EN LA CONVERSION DEL PAQUETE
	 error = -5;
	 } else {
	 //EL PAQUETE RECIBIDO NO ES DE TIPO ESCRITURA
	 printf("El paquete no es de tipo escritura.\n");
	 if (esPaqueteError(paquete.type) && (paquete.pLength != 0)) {
	 printf("El paquete es de tipo error.\n");
	 if (strcmp(paquete.payLoad, ERROR_CAMBIAR_CONEXION_A_RAID1) == 0) {
	 printf("Corresponde hacer la conexion con el raid, cambio las conexiones.\n");
	 pthread_mutex_lock(&mutexUsandoPoolConexiones);
	 cambiarConexionActivaARaid1();
	 pthread_mutex_unlock(&mutexUsandoPoolConexiones);
	 } else if (strcmp(paquete.payLoad, ERROR_CAMBIAR_CONEXION_A_DISCO) == 0) {
	 printf("No debo conectarme al raid, hay un solo disco, cambio las conexiones.\n");
	 pthread_mutex_lock(&mutexUsandoPoolConexiones);
	 cambiarConexionActivaADisco();
	 pthread_mutex_unlock(&mutexUsandoPoolConexiones);
	 } else if (strcmp(paquete.payLoad, ERROR_NINGUN_DISCO) == 0) {
	 printf("No hay ningun disco.\n");
	 error = -6;
	 } else {
	 printf("No entiendo el mensaje de error.");
	 }
	 }
	 recibiBootSector = 0;
	 }
	 } else if (error == 1) {
	 //EL DESCRIPTOR NO ESTABA OCUPADO, CIERRO LA CONEXION Y LA CAMBIO POR OTRA
	 printf("Error en el recibimiento, el descriptor era incorrecto, se cerrara la conexion.\n");
	 error = 0;
	 pthread_mutex_lock(&mutexUsandoPoolConexiones);
	 error = cerrarConexion(descriptor);
	 pthread_mutex_unlock(&mutexUsandoPoolConexiones);
	 sleep(1);
	 } else if (error == 2) {
	 //HUBO UN ERROR EN EL RECIBIMIENTO, CIERRO LA CONEXION Y LA CAMBIO POR OTRA
	 printf("Error en el recibimiento, se cerrara la conexion.\n");
	 error = 0;
	 pthread_mutex_lock(&mutexUsandoPoolConexiones);
	 error = cerrarConexion(descriptor);
	 pthread_mutex_unlock(&mutexUsandoPoolConexiones);
	 sleep(1);
	 } else {
	 printf("Error en el recibimiento.\n");
	 //HUBO UN ERROR EN EL RECIBIMIENTO
	 error = -4;
	 }
	 } else if (error == 1) {
	 //EL DESCRIPTOR NO ESTABA OCUPADO, CIERRO LA CONEXION Y LA CAMBIO POR OTRA
	 printf("Error en el envio, el descriptor era incorrecto, se cerrara la conexion.\n");
	 error = 0;
	 pthread_mutex_lock(&mutexUsandoPoolConexiones);
	 error = cerrarConexion(descriptor);
	 pthread_mutex_unlock(&mutexUsandoPoolConexiones);
	 sleep(1);
	 } else if (error == 2) {
	 printf("Error en el envio, se cerrara la conexion.\n");
	 //HUBO UN ERROR EN EL ENVIO, CIERRO LA CONEXION Y LA CAMBIO POR OTRA
	 error = 0;
	 pthread_mutex_lock(&mutexUsandoPoolConexiones);
	 error = cerrarConexion(descriptor);
	 pthread_mutex_unlock(&mutexUsandoPoolConexiones);
	 sleep(1);
	 } else {
	 printf("Error en el envio.\n");
	 //HUBO UN ERROR EN EL ENVIO
	 error = -3;
	 }
	 } else
	 //HUBO UN ERROR EN LA CONVERSION DE PAQUETE
	 error = -2;
	 } else
	 //HUBO UN ERROR AL OBTENER UNA CONEXION
	 error = -1;
	 }

	 printf("--------------------fin-leerBootSector--------------------\n");
	 return error;*/
}
//--------------------------------------------------
//MANEJO DE BLOQUES
//--------------------------------------------------

int8_t leerBloque(uint64_t sectorInicio, char* contenido) {

	if (!usarSockets) {
		if (imprimirDebug) {
			/**/ //printf("--------------------leerBloque--------------------\n");
		}
		FILE* fp;
		fp = fopen("/home/utn_so/Escritorio/fat32.disk", "r");
		if (imprimirDebug) {
			/**/
			//printf("Voy a leer a partir del byte [%d].\n", (sectorInicio * bootSector.bytesSector));
		}
		fseek(fp, (sectorInicio * bootSector.bytesSector), SEEK_SET);
		fread(contenido, sizeof(char), TAMANIO_BLOQUE, fp);
		fclose(fp);
		if (imprimirDebug) {
			uint16_t i;
			/*for (i = 0; i < TAMANIO_BLOQUE; i++) {
			 printf("[%d].\n", contenido[i]);
			 }*/
		}
		if (imprimirDebug) {
			/**/
			//printf("--------------------leerBloque--------------------\n");
		}
		return 0;
	} else {

		if (imprimirDebug) {
			printf("--------------------leerBloque--------------------\n");
		}
		int8_t error = 0;

		t_paquete_lectura paqueteLectura;
		paqueteLectura.type = TIPO_LECTURA;
		paqueteLectura.pLength = 8 * sizeof(uint64_t);
		paqueteLectura.payLoad = (uint64_t*) malloc(paqueteLectura.pLength);
		memset(paqueteLectura.payLoad, 0, paqueteLectura.pLength);
		paqueteLectura.payLoad[0] = sectorInicio;
		paqueteLectura.payLoad[1] = sectorInicio + 1;
		paqueteLectura.payLoad[2] = sectorInicio + 2;
		paqueteLectura.payLoad[3] = sectorInicio + 3;
		paqueteLectura.payLoad[4] = sectorInicio + 4;
		paqueteLectura.payLoad[5] = sectorInicio + 5;
		paqueteLectura.payLoad[6] = sectorInicio + 6;
		paqueteLectura.payLoad[7] = sectorInicio + 7;

		t_controlBloque controlBloque[SECTORES_BLOQUE];
		controlBloque[0].numSector = sectorInicio;
		controlBloque[1].numSector = sectorInicio + 1;
		controlBloque[2].numSector = sectorInicio + 2;
		controlBloque[3].numSector = sectorInicio + 3;
		controlBloque[4].numSector = sectorInicio + 4;
		controlBloque[5].numSector = sectorInicio + 5;
		controlBloque[6].numSector = sectorInicio + 6;
		controlBloque[7].numSector = sectorInicio + 7;

		int8_t recibiBloque = 0;
		while (!recibiBloque) {
			if (imprimirDebug) {
				printf("Hago el pedido de un bloque.\n");
			}
			controlBloque[0].fueRecibido = 0;
			controlBloque[1].fueRecibido = 0;
			controlBloque[2].fueRecibido = 0;
			controlBloque[3].fueRecibido = 0;
			controlBloque[4].fueRecibido = 0;
			controlBloque[5].fueRecibido = 0;
			controlBloque[6].fueRecibido = 0;
			controlBloque[7].fueRecibido = 0;

			char* contenidoAux = (char*) malloc(SECTORES_BLOQUE * bootSector.bytesSector);
			memset(contenidoAux, '\0', SECTORES_BLOQUE * bootSector.bytesSector);

			t_paquete paqueteEnviado;
			paqueteEnviado.type = 0;
			paqueteEnviado.pLength = 0;
			paqueteEnviado.payLoad = NULL;
			error = paqueteLecturaAPaquete(paqueteLectura, &paqueteEnviado);

			if (imprimirDebug) {
				printf("Envio:\n");
				printf("Tipo: [%d]\n", paqueteLectura.type);
				printf("PLength: [%d]\n", paqueteLectura.pLength);
				uint8_t i;
				for (i = 0; i < SECTORES_BLOQUE; i++) {
					printf("Sector [%d]\n", paqueteLectura.payLoad[i]);
				}
			}

			if (!error) {

				char* cadenaAEnviar;

				error = desempaquetar(paqueteEnviado, &cadenaAEnviar);

				if (!error) {

					char* cadenaRecibida = (char*) malloc(MAX_BUFFER);

					error = hacerPedido(cadenaAEnviar, (paqueteEnviado.pLength + 3), cadenaRecibida);

					if (!error) {

						t_paquete paqueteRecibido;
						paqueteRecibido.type = 0;
						paqueteRecibido.pLength = 0;
						paqueteRecibido.payLoad = NULL;

						error = empaquetar(cadenaRecibida, &paqueteRecibido);

						if (!error) {

							if (esPaqueteEscritura(paqueteRecibido.type)) {

								t_paquete_escritura paqueteEscritura;

								error = paqueteAPaqueteEscritura(paqueteRecibido, &paqueteEscritura);

								if (!error) {

									uint8_t i;
									for (i = 0; i < SECTORES_BLOQUE; i++) {
										if (imprimirDebug) {
											printf("Recibi el sector: %d\n", paqueteEscritura.payLoad[i].numSector);
										}
										uint8_t j;
										for (j = 0; j < SECTORES_BLOQUE && controlBloque[j].numSector != paqueteEscritura.payLoad[i].numSector; i++)
											;
										if ((j < SECTORES_BLOQUE) && (controlBloque[j].numSector == paqueteEscritura.payLoad[i].numSector)) {
											controlBloque[j].fueRecibido = 1;
											if (imprimirDebug) {
												printf("Copio el contenido enviado.\n");
											}
											memcpy(contenidoAux + (sectorInicio - controlBloque[j].numSector), paqueteEscritura.payLoad[i].contenidoSector, bootSector.bytesSector);
										}

									}

									for (i = 0; i < SECTORES_BLOQUE; i++) {
										if (imprimirDebug) {
											printf("Sector %d : %d\n", controlBloque[i].numSector, controlBloque[i].fueRecibido);
										}
									}

									for (i = 0; i < SECTORES_BLOQUE && controlBloque[i].fueRecibido; i++) {
										printf("El sector [%d] fue recibido.\n", controlBloque[i].numSector);
									}
									if (i == 8) {
										if (imprimirDebug) {
											printf("Se recibio el bloque esperado.\n");
										}
										memcpy(contenido, contenidoAux, 4096);
										recibiBloque = 1;
									} else {
										if (imprimirDebug) {
											printf("No se recibio el bloque esperado.\n");
										}
										recibiBloque = 0;
									}
								} else {
									//HUBO UN ERROR EN LA CONVERSION DEL PAQUETE
									recibiBloque = 0;
								}
								free(paqueteEscritura.payLoad);
							} else {
								if (imprimirDebug) {
									printf("El paquete no es de tipo escritura.\n");
								}
								//EL PAQUETE RECIBIDO NO ES DE TIPO ESCRITURA
								if (esPaqueteError(paqueteRecibido.type) && (paqueteRecibido.pLength != 0)) {
									if (imprimirDebug) {
										printf("El paquete es de tipo error.\n");
									}
									if (strcmp(paqueteRecibido.payLoad, ERROR_CAMBIAR_CONEXION_A_RAID1) == 0) {
										if (imprimirDebug) {
											printf("Corresponde hacer la conexion con el raid, cambio las conexiones.\n");
										}
										pthread_mutex_lock(&mutexUsandoPoolConexiones);
										cambiarConexionActivaARaid1();
										pthread_mutex_unlock(&mutexUsandoPoolConexiones);
									} else if (strcmp(paqueteRecibido.payLoad, ERROR_CAMBIAR_CONEXION_A_DISCO) == 0) {
										if (imprimirDebug) {
											printf("No debo conectarme al raid, hay un solo disco, cambio las conexiones.\n");
										}
										pthread_mutex_lock(&mutexUsandoPoolConexiones);
										cambiarConexionActivaADisco();
										pthread_mutex_unlock(&mutexUsandoPoolConexiones);
									} else if (strcmp(paqueteRecibido.payLoad, ERROR_NINGUN_DISCO) == 0) {
										if (imprimirDebug) {
											printf("No hay ningun disco.\n");
										}
									} else {
										if (imprimirDebug) {
											printf("No entiendo el mensaje de error.");
										}
									}
								} else if (esPaqueteError(paqueteRecibido.type)) {
									if (imprimirDebug) {
										printf("Se ha recibido un paquete de error vacio.\n");
									}
								} else {
									if (imprimirDebug) {
										printf("Se ha recibido un paquete de tipo no esperado.\n");
									}
								}
								recibiBloque = 0;
							}
						} else {
							//HUBO UN ERROR EN LA CONVERSION DEL PAQUETE, DE CADENA A PAQUETE
							recibiBloque = 0;
						}
						free(paqueteRecibido.payLoad);
					} else {
						//ERROR AL HACER EL PEDIDO
						recibiBloque = 0;
					}
					free(cadenaRecibida);
				} else {
					//HUBO UN ERROR EN LA CONVERSION DEL PAQUETE, DE PAQUETE A CADENA
					recibiBloque = 0;
				}
				free(cadenaAEnviar);
			} else {
				//HUBO UN ERROR EN LA CONVERSION DE PAQUETE, DE PAQUETE LECTURA A PAQUETE
				recibiBloque = 0;
			}
			free(paqueteEnviado.payLoad);
			free(contenidoAux);
		}
		free(paqueteLectura.payLoad);
		if (imprimirDebug) {
			printf("--------------------fin-leerBloque--------------------\n");
		}
		return error;
	}
}

int8_t escribirBloque(uint64_t sectorInicio, char* contenido) {

	if (!usarSockets) {
		FILE* fp;
		fp = fopen("/home/utn_so/Escritorio/fat32.disk", "r+");

		uint32_t inicio = sectorInicio * bootSector.bytesSector;

		fseek(fp, inicio, SEEK_SET);
		if (imprimirDebug) {
			/**/
			printf("Voy a escribir a partir del byte [%d].\n", inicio);
		}
		fwrite(contenido, 1, SECTORES_BLOQUE * bootSector.bytesSector, fp);

		fclose(fp);
		return 0;
	} else {

		if (imprimirDebug) {
			printf("--------------------escribirBloque--------------------\n");
		}
		int8_t error = 0;

		t_paquete_escritura paqueteEscritura;
		paqueteEscritura.type = TIPO_ESCRITURA;
		paqueteEscritura.pLength = 8 * sizeof(payLoad_Escritura);
		paqueteEscritura.payLoad = (payLoad_Escritura*) malloc(paqueteEscritura.pLength);
		memset(paqueteEscritura.payLoad, 0, paqueteEscritura.pLength);

		paqueteEscritura.payLoad[0].numSector = sectorInicio;
		memcpy(paqueteEscritura.payLoad[0].contenidoSector, contenido, 512);

		paqueteEscritura.payLoad[1].numSector = sectorInicio + 1;
		memcpy(paqueteEscritura.payLoad[1].contenidoSector, contenido + (1 * 512), 512);

		paqueteEscritura.payLoad[2].numSector = sectorInicio + 2;
		memcpy(paqueteEscritura.payLoad[2].contenidoSector, contenido + (2 * 512), 512);

		paqueteEscritura.payLoad[3].numSector = sectorInicio + 3;
		memcpy(paqueteEscritura.payLoad[3].contenidoSector, contenido + (3 * 512), 512);

		paqueteEscritura.payLoad[4].numSector = sectorInicio + 4;
		memcpy(paqueteEscritura.payLoad[4].contenidoSector, contenido + (4 * 512), 512);

		paqueteEscritura.payLoad[5].numSector = sectorInicio + 5;
		memcpy(paqueteEscritura.payLoad[5].contenidoSector, contenido + (5 * 512), 512);

		paqueteEscritura.payLoad[6].numSector = sectorInicio + 6;
		memcpy(paqueteEscritura.payLoad[6].contenidoSector, contenido + (6 * 512), 512);

		paqueteEscritura.payLoad[7].numSector = sectorInicio + 7;
		memcpy(paqueteEscritura.payLoad[7].contenidoSector, contenido + (7 * 512), 512);

		int8_t envieBloque = 0;
		while (!envieBloque) {
			if (imprimirDebug) {
				printf("Hago la escritura de un bloque.\n");
			}

			t_paquete paqueteEnviado;
			paqueteEnviado.type = 0;
			paqueteEnviado.pLength = 0;
			paqueteEnviado.payLoad = NULL;
			error = paqueteEscrituraAPaquete(paqueteEscritura, &paqueteEnviado);

			if (imprimirDebug) {
				printf("Envio:\n");
				printf("Tipo: [%d]\n", paqueteEscritura.type);
				printf("PLength: [%d]\n", paqueteEscritura.pLength);
				uint8_t i;
				for (i = 0; i < SECTORES_BLOQUE; i++) {
					printf("Sector [%d]\n", paqueteEscritura.payLoad[i]);
				}
			}

			if (!error) {

				char* cadenaAEnviar;

				error = desempaquetar(paqueteEnviado, &cadenaAEnviar);

				if (!error) {

					char* cadenaRecibida = (char*) malloc(MAX_BUFFER);

					error = hacerPedido(cadenaAEnviar, (paqueteEnviado.pLength + 3), cadenaRecibida);

					if (!error) {

						t_paquete paqueteRecibido;
						paqueteRecibido.type = 0;
						paqueteRecibido.pLength = 0;
						paqueteRecibido.payLoad = NULL;

						error = empaquetar(cadenaRecibida, &paqueteRecibido);

						if (!error) {

							if (esPaqueteError(paqueteRecibido.type) && (paqueteRecibido.pLength != 0)) {
								if (imprimirDebug) {
									printf("El paquete es de tipo error.\n");
								}
								if (strcmp(paqueteRecibido.payLoad, "ESCRIBI") == 0) {
									if (imprimirDebug) {
										printf("Se pudo escribir el bloque.\n");
									}
									envieBloque = 1;
								} else if (strcmp(paqueteRecibido.payLoad, ERROR_CAMBIAR_CONEXION_A_RAID1) == 0) {
									if (imprimirDebug) {
										printf("Corresponde hacer la conexion con el raid, cambio las conexiones.\n");
									}
									pthread_mutex_lock(&mutexUsandoPoolConexiones);
									cambiarConexionActivaARaid1();
									pthread_mutex_unlock(&mutexUsandoPoolConexiones);
									envieBloque = 0;
								} else if (strcmp(paqueteRecibido.payLoad, ERROR_CAMBIAR_CONEXION_A_DISCO) == 0) {
									if (imprimirDebug) {
										printf("No debo conectarme al raid, hay un solo disco, cambio las conexiones.\n");
									}
									pthread_mutex_lock(&mutexUsandoPoolConexiones);
									cambiarConexionActivaADisco();
									pthread_mutex_unlock(&mutexUsandoPoolConexiones);
									envieBloque = 0;
								} else if (strcmp(paqueteRecibido.payLoad, ERROR_NINGUN_DISCO) == 0) {
									if (imprimirDebug) {
										printf("No hay ningun disco.\n");
									}
									envieBloque = 0;
								} else {
									if (imprimirDebug) {
										printf("No entiendo el mensaje de error.");
									}
									envieBloque = 0;
								}
							} else if (esPaqueteError(paqueteRecibido.type)) {
								if (imprimirDebug) {
									printf("Se ha recibido un paquete de error vacio.\n");
								}
								envieBloque = 0;
							} else {
								if (imprimirDebug) {
									printf("Se ha recibido un paquete de tipo no esperado.\n");
								}
								envieBloque = 0;
							}
						} else {
							//HUBO UN ERROR EN LA CONVERSION DEL PAQUETE, DE CADENA A PAQUETE
							envieBloque = 0;
						}
						free(paqueteRecibido.payLoad);
					} else {
						//ERROR AL HACER EL PEDIDO
						envieBloque = 0;
					}
					free(cadenaRecibida);
				} else {
					//HUBO UN ERROR EN LA CONVERSION DEL PAQUETE, DE PAQUETE A CADENA
					envieBloque = 0;
				}
				free(cadenaAEnviar);
			} else {
				//HUBO UN ERROR EN LA CONVERSION DE PAQUETE, DE PAQUETE ESCRITURA A PAQUETE
				envieBloque = 0;
			}
			free(paqueteEnviado.payLoad);
		}
		free(paqueteEscritura.payLoad);
		if (imprimirDebug) {
			printf("--------------------fin-escribirBloque--------------------\n");
		}
		return error;
	}
}

//--------------------------------------------------
//MANEJO DE LA FAT REGION Y TABLA FAT
//--------------------------------------------------

int8_t leerTablaFat(uint32_t** tablaFat) {
	if (imprimirDebug) {
		printf("--------------------leerTablaFat--------------------\n");
	}

	if (primeraLecturaFat) {
		div_t division1 = div(bootSector.sectoresReservados * bootSector.bytesSector, TAMANIO_BLOQUE);
		uint64_t offset = division1.rem;

		uint32_t primerBloqueFat = division1.quot;

		div_t division2 = div((bootSector.sectoresReservados + bootSector.sectoresPorFat) * bootSector.bytesSector, TAMANIO_BLOQUE);
		uint32_t ultimoBloqueFat;
		if (division2.rem == 0) {
			ultimoBloqueFat = division2.quot;
		} else {
			ultimoBloqueFat = division2.quot + 1;
		}
		char* contenidoAux = (char*) malloc(((ultimoBloqueFat - primerBloqueFat) + 1) * TAMANIO_BLOQUE);
		memset(contenidoAux, '\0', ((ultimoBloqueFat - primerBloqueFat) + 1) * TAMANIO_BLOQUE);

		int8_t error = 0;
		uint64_t i;
		uint64_t j;
		for (i = primerBloqueFat, j = 0; i <= ultimoBloqueFat && !error; i++, j++) {
			error = leerBloque((i * bootSector.sectoresCluster), contenidoAux + (j * TAMANIO_BLOQUE));
		}

		(*tablaFat) = (uint32_t*) malloc(bootSector.sectoresPorFat * bootSector.bytesSector);
		tablaFatEnMem = (uint32_t*) malloc(bootSector.sectoresPorFat * bootSector.bytesSector);

		if (!error) {
			for (j = 0, i = offset; i < (bootSector.sectoresPorFat * bootSector.bytesSector) - 3; j++, i += 4) {
				memcpy((*tablaFat) + j, contenidoAux + i, 4);
				memcpy(tablaFatEnMem + j, contenidoAux + i, 4);
			}
			return 0;
		} else {
			return -1;
		}
	}else{
		(*tablaFat) = (uint32_t*) malloc(bootSector.sectoresPorFat * bootSector.bytesSector);
		memset((*tablaFat), 0, bootSector.sectoresPorFat * bootSector.bytesSector);
		memcpy((*tablaFat), tablaFatEnMem, bootSector.sectoresPorFat * bootSector.bytesSector);
	}

	/*(*tablaFat) = (uint32_t*) malloc(bootSector.sectoresPorFat * bootSector.bytesSector);
	 memset(*tablaFat, '\0', bootSector.sectoresPorFat * bootSector.bytesSector);
	 FILE* fp;
	 fp = fopen("/home/utn_so/Escritorio/fat32.disk", "r");
	 fseek(fp, (bootSector.sectoresReservados * bootSector.bytesSector), SEEK_SET);
	 char* fat = (char*) malloc(bootSector.sectoresPorFat * bootSector.bytesSector);
	 memset(fat, '\0', bootSector.sectoresPorFat * bootSector.bytesSector);
	 fread(fat, sizeof(char), (bootSector.sectoresPorFat * bootSector.bytesSector), fp);
	 memcpy(*tablaFat, fat, (bootSector.sectoresPorFat * bootSector.bytesSector));
	 fclose(fp);
	 printf("--------------------fin-leerTablaFat--------------------\n");
	 return 0;*/

	/*printf("--------------------leerTablaFat--------------------\n");
	 int8_t error = 0;
	 uint32_t sectoresFat = bootSector.sectoresPorFat;
	 div_t division = div(sectoresFat, 8); //REDONDEO LA TABLA FAT PARA ARRIBA PARA PEDIR POR CLUSTER
	 uint32_t sectoresFatRedondeados;

	 if (division.rem == 0)
	 sectoresFatRedondeados = sectoresFat;
	 else
	 sectoresFatRedondeados = (division.quot + 1) * 8;

	 uint32_t* tablaFatAux = (uint32_t*) malloc(sectoresFatRedondeados * bootSector.bytesSector);
	 memset(tablaFatAux, 0, sectoresFatRedondeados * bootSector.bytesSector);
	 uint32_t i;
	 for (i = 0; i < sectoresFatRedondeados - 7 && !error; i += SECTORES_BLOQUE) {
	 uint64_t sectorInicio = bootSector.sectoresReservados + i;
	 error = leerBloque(sectorInicio, (char*) tablaFatAux + ((i * bootSector.bytesSector / sizeof(uint32_t))));
	 }
	 if (!error) {
	 (*tablaFat) = (uint32_t*) malloc(sectoresFat * bootSector.bytesSector);
	 memset(*tablaFat, 0, sectoresFatRedondeados * bootSector.bytesSector);
	 for (i = 0; i < (bootSector.sectoresPorFat * bootSector.bytesSector / sizeof(uint32_t)); i++) {
	 (*tablaFat)[i] = tablaFatAux[i];
	 }
	 }
	 printf("--------------------fin-leerTablaFat--------------------\n");
	 return error;*/
}

int8_t escribirTablaFat(uint32_t* tablaFat) {
	if (imprimirDebug) {
		printf("--------------------escribirTablaFat--------------------\n");
	}

	//ACTUALIZO LA TABLA FAT EN MEMORIA
	memcpy(tablaFatEnMem, tablaFat, bootSector.sectoresPorFat * bootSector.bytesSector);

	//Y EN EL DISCO
	div_t division1 = div(bootSector.sectoresReservados * bootSector.bytesSector, TAMANIO_BLOQUE);
	uint64_t offset = division1.rem;

	uint32_t primerBloqueFat = division1.quot;

	div_t division2 = div((bootSector.sectoresReservados + bootSector.sectoresPorFat) * bootSector.bytesSector, TAMANIO_BLOQUE);
	uint32_t ultimoBloqueFat;
	if (division2.rem == 0) {
		ultimoBloqueFat = division2.quot;
	} else {
		ultimoBloqueFat = division2.quot + 1;
	}
	char* contenidoAux = (char*) malloc(TAMANIO_BLOQUE);

	//LEO Y ESCRIBO LOS BLOQUES
	//PRIMER BLOQUE
	uint32_t i = primerBloqueFat;
	uint32_t j;
	uint32_t k;
	memset(contenidoAux, '\0', TAMANIO_BLOQUE);
	int8_t error = leerBloque((i * TAMANIO_BLOQUE / bootSector.bytesSector), contenidoAux);

	if (!error) {
		//SOBREESCRIBO LO NECESARIO
		for (j = offset, k = 0; j < (TAMANIO_BLOQUE - 3); j += 4, k++) {
			memcpy(contenidoAux + j, tablaFat + k, 4);
		}

		//ESCRIBO EL BLOQUE CON LOS DATOS SOBRESCRITOS
		error = escribirBloque((i * TAMANIO_BLOQUE / bootSector.bytesSector), contenidoAux);

		if (!error) {
			//ESCRIBO LOS BLOQUES DEL MEDIO
			for (i = primerBloqueFat + 1, j = 0; i < ultimoBloqueFat && !error; i++, j++) {
				error = escribirBloque((i * TAMANIO_BLOQUE / bootSector.bytesSector), (char*)(tablaFat + ((offset + (j * TAMANIO_BLOQUE)) / sizeof(uint32_t))));
			}

			if(!error) {
				//ESCRIBO EL BLOQUE FINAL
						i = ultimoBloqueFat;
						if(division2.rem == 0) {
							error = escribirBloque((i * TAMANIO_BLOQUE / bootSector.bytesSector), (char*)(tablaFat + ((offset + (j * TAMANIO_BLOQUE)) / sizeof(uint32_t))));

							if(!error) {
								return 0;
							} else {
								//ERROR AL ESCRIBIR EL ULTIMO BLOQUE
						return -6;
					}
				} else {
					memset(contenidoAux, '\0', TAMANIO_BLOQUE);
					error = leerBloque((i * TAMANIO_BLOQUE / bootSector.bytesSector), contenidoAux);
					if(!error) {
						//SOBREESCRIBO LO NECESARIO
						k = ((offset + (j * TAMANIO_BLOQUE)) / sizeof(uint32_t));
						for(j = 0; j < division2.rem - 3; j += 4, k++) {
							memcpy(contenidoAux + j, tablaFat + k, 4);
						}

						//ESCRIBO EL ULTIMO BLOQUE
						error = escribirBloque((i * TAMANIO_BLOQUE / bootSector.bytesSector), contenidoAux);
						if(!error) {
							return 0;
						} else {
							//ERROR AL ESCRIBIR EL ULTIMO BLOQUE
							return -5;
						}
					} else {
						//ERROR AL LEER EL ULTIMO BLOQUE
						return -4;
					}
				}
			} else {
				//ERROR AL ESCRIBIR UNO DE LOS BLOQUES DEL MEDIO
				return -3;
			}
		} else {
			//ERROR AL ESCRIBIR EL PRIMER BLOQUE
			return -2;
		}
	} else {
		//ERROR AL LEER EL PRIMER BLOQUE
		return -1;
	}

	/*FILE* fp;
	 fp = fopen("/home/utn_so/Escritorio/fat32.disk", "r+");
	 fseek(fp,
	 (bootSector.sectoresReservados * bootSector.bytesSector), SEEK_SET);
	 fwrite(tablaFat, 1, bootSector.sectoresPorFat * bootSector.bytesSector, fp);
	 fclose(fp);
	 printf("--------------------fin-leerTablaFat--------------------\n");
	 return 0;*/

	/*printf("--------------------escribirTablaFat--------------------\n");
	 int8_t error = 0;
	 uint32_t sectoresFat = bootSector.sectoresPorFat;
	 div_t division = div(sectoresFat, 8); //REDONDEO LA TABLA FAT PARA ARRIBA PARA PEDIR POR CLUSTER
	 uint32_t sectoresFatRedondeados;

	 if (division.rem == 0)
	 sectoresFatRedondeados = sectoresFat;
	 else
	 sectoresFatRedondeados = (division.quot + 1) * 8;

	 uint32_t i;
	 for (i = 0; i < sectoresFatRedondeados - 7 && !error; i += SECTORES_BLOQUE) {
	 uint64_t sectorInicio = bootSector.sectoresReservados + i;
	 error = escribirBloque(sectorInicio, (char*) tablaFat + ((i * bootSector.bytesSector / sizeof(uint32_t))));
	 }
	 printf("--------------------fin-escribirTablaFat--------------------\n");
	 return error;*/
}

int8_t actualizarTablaFat(uint32_t* tablaFat) {
	int8_t error = 0;
	error = escribirTablaFat(tablaFat);
	if (!error) {
		error = escribirSegundaTablaFat(tablaFat);
	}
	return error;
}

int8_t modificarTablaFat(nodoCluster** cClusterFte, nodoCluster** cClusterFin, uint32_t cantClustersNecesarios) {
	uint32_t* tablaFat;
	int8_t error = 0;

	uint16_t cantClustersActuales = tamanioColaClusters(*cClusterFte, *cClusterFin);

	if (imprimirDebug) {
		/**/
		printf("Tengo un archivo con [%d] clusters asociados y necesito [%d].\n", cantClustersActuales, cantClustersNecesarios);
	}

	if (cantClustersActuales < cantClustersNecesarios) {
		if (imprimirDebug) {
			/**/printf("Tengo que agregar Clusters.\n");
		}
		//TENGO QUE AGREGAR CLUSTERS
		uint32_t numClusterFinal = (*cClusterFin)->numCluster;
		pthread_mutex_lock(&mutexUsandoFat);
		//NECESITO QUE EN ESTE INTERVALO NADIE MODIFIQUE LAS FAT
		if (imprimirDebug) {
			/**/
			printf("Leo la tabla fat.\n");
		}
		error = leerTablaFat(&tablaFat);
		if (!error) {
			uint32_t valorClusterFinal = tablaFat[numClusterFinal];
			if (tablaFat[numClusterFinal] >= 268435448) {
				//EL ULTIMO CLUSTER CORRESPONDE AL ULTIMO DEL ARCHIVO
				if (imprimirDebug) {
					/**/printf("El cluster [%d] corresponde al ultimo del archivo.\n", numClusterFinal);
				}
				uint16_t i;
				for (i = 0; i < (cantClustersNecesarios - cantClustersActuales) && !error; i++) {
					uint32_t j;
					for (j = 2; j < ((bootSector.sectoresPorFat * bootSector.bytesSector) / sizeof(uint32_t)) && !estaLibreCluster(tablaFat[j]); j++)
						;
					if (j < ((bootSector.sectoresPorFat * bootSector.bytesSector) / sizeof(uint32_t)) && estaLibreCluster(tablaFat[j])) {
						//ENCONTRE UN CLUSTER LIBRE
						if (imprimirDebug) {
							/**/printf("El cluster [%d] esta libre.\n", j);
						}
						tablaFat[j] = valorClusterFinal;
						tablaFat[numClusterFinal] = j;
						numClusterFinal = j;
						error = encolarCluster(cClusterFte, cClusterFin, j);
					} else {
						//NO HAY CLUSTERS LIBRES
						if (imprimirDebug) {
							/**/printf("No quedan clusters libres.\n");
						}
						error = -3;
					}
				}
				if (!error) {
					error = actualizarTablaFat(tablaFat);
				}
			} else {
				//EL CLUSTER FINAL DE LA COLA NO CORRESPONDE CON EL FINAL DEL ARCHIVO O DIRECTORIO
				error = -2;
			}
		} else {
			//ERROR AL LEER LA TABLA FAT
			error = -1;
		}
		pthread_mutex_unlock(&mutexUsandoFat);
	} else if (cantClustersActuales > cantClustersNecesarios) {
		if (imprimirDebug) {
			/**/printf("Tengo que sacar clusters.\n");
		}
		//TENGO QUE SACAR CLUSTERS
		uint32_t numClusterFinal = (*cClusterFin)->numCluster;
		pthread_mutex_lock(&mutexUsandoFat);
		if (imprimirDebug) {
			/**/
			printf("Leo la tabla fat.\n");
		}
		error = leerTablaFat(&tablaFat);
		if (!error) {
			uint32_t valorClusterFinal = tablaFat[numClusterFinal];
			if (tablaFat[numClusterFinal] >= 268435448) {
				if (imprimirDebug) {
					/**/printf("El cluster [%d] corresponde al ultimo del archivo.\n", numClusterFinal);
				}
				//EL ULTIMO CLUSTER CORRESPONDE AL ULTIMO DEL ARCHIVO
				uint16_t i;
				for (i = 0; i < (cantClustersActuales - cantClustersNecesarios) && !error; i++) {
					if (cClusterFte != NULL) {
						if (imprimirDebug) {
							/**/printf("Desencolo un cluster.\n");
						}
						error = desencolarClusterFinal(cClusterFte, cClusterFin, &numClusterFinal);
						if (imprimirDebug) {
							/**/
							printf("Habilito el cluster [%d].\n", numClusterFinal);
						}
						tablaFat[numClusterFinal] = 0;

					} else {
						//LA COLA DE CLUSTERS SE VACIO ANTES DE LO PREVISTO
						if (imprimirDebug) {
							/**/printf("La cola de clusters se vacio antes de lo previsto.\n");
						}
						error = -3;
					}
				}
				if (*cClusterFin != NULL) {
					if (imprimirDebug) {
						/**/printf("Le asigno al cluster [%d] el valor [%d].\n", (*cClusterFin)->numCluster, valorClusterFinal);
					}
					tablaFat[((*cClusterFin)->numCluster)] = valorClusterFinal;
				}
				if (!error) {
					if (imprimirDebug) {
						/**/printf("Actualizo la tabla fat.\n");
					}
					error = actualizarTablaFat(tablaFat);
				}
			} else {
				//EL CLUSTER FINAL DE LA COLA NO CORRESPONDE CON EL FINAL DEL ARCHIVO O DIRECTORIO
				if (imprimirDebug) {
					/**/printf("El cluster final de la cola no corresponde con el final del archivo.\n");
				}
				error = -2;
			}
		} else {
			//ERROR AL LEER LA TABLA FAT
			if (imprimirDebug) {
				/**/printf("Error al leer la tabla fat.\n");
			}
			error = -1;
		}
		pthread_mutex_unlock(&mutexUsandoFat);
	}
	return error;
}

uint32_t obtenerClusterLibre() {
	int8_t error = 0;
	uint32_t* tablaFat;
	pthread_mutex_lock(&mutexUsandoFat);
	error = leerTablaFat(&tablaFat);
	if (!error) {
		uint32_t i = 2;
		uint32_t longFat = bootSector.sectoresPorFat * bootSector.bytesSector / sizeof(uint32_t);
		while (i < longFat && tablaFat[i] != 0)
			i++;
		if (i < longFat && tablaFat[i] == 0) {
			tablaFat[i] = 268435448;
			error = actualizarTablaFat(tablaFat);
			if (!error) {
				pthread_mutex_unlock(&mutexUsandoFat);
				return i;
			} else {
				pthread_mutex_unlock(&mutexUsandoFat);
				return 0;
			}
		} else {
			pthread_mutex_unlock(&mutexUsandoFat);
			return 0;
		}
	} else {
		pthread_mutex_unlock(&mutexUsandoFat);
		return 0;
	}
}

int8_t leerSegundaTablaFat(uint32_t** tablaFat) {
	if (imprimirDebug) {
		printf("--------------------leerTablaFat--------------------\n");
	}

	div_t division1 = div((bootSector.sectoresReservados + bootSector.sectoresPorFat) * bootSector.bytesSector, TAMANIO_BLOQUE);
	uint64_t offset = division1.rem;

	uint32_t primerBloqueFat = division1.quot;

	div_t division2 = div((bootSector.sectoresReservados + (bootSector.sectoresPorFat * bootSector.cantidadTablasFat)) * bootSector.bytesSector, TAMANIO_BLOQUE);
	uint32_t ultimoBloqueFat;
	if (division2.rem == 0) {
		ultimoBloqueFat = division2.quot;
	} else {
		ultimoBloqueFat = division2.quot + 1;
	}
	char* contenidoAux = (char*) malloc(((ultimoBloqueFat - primerBloqueFat) + 1) * TAMANIO_BLOQUE);
	memset(contenidoAux, '\0', ((ultimoBloqueFat - primerBloqueFat) + 1) * TAMANIO_BLOQUE);

	int8_t error = 0;
	uint64_t i;
	uint64_t j;
	for (i = primerBloqueFat, j = 0; i <= ultimoBloqueFat && !error; i++, j++) {
		error = leerBloque((i * bootSector.sectoresCluster), contenidoAux + (j * TAMANIO_BLOQUE));
	}

	(*tablaFat) = (uint32_t*) malloc(bootSector.sectoresPorFat * bootSector.bytesSector);

	if (!error) {
		for (j = 0, i = offset; i < (bootSector.sectoresPorFat * bootSector.bytesSector) - 3; j++, i += 4) {
			memcpy((*tablaFat) + j, contenidoAux + i, 4);
		}
		return 0;
	} else {
		return -1;
	}

	/*(*tablaFat) = (uint32_t*) malloc(bootSector.sectoresPorFat * bootSector.bytesSector);
	 memset(*tablaFat, 0, bootSector.sectoresPorFat * bootSector.bytesSector);
	 FILE* fp;
	 fp = fopen("/home/utn_so/Escritorio/fat32.disk", "r");
	 fseek(fp, ((bootSector.sectoresReservados + bootSector.sectoresPorFat) * bootSector.bytesSector), SEEK_SET);
	 char* fat = (char*) malloc(bootSector.sectoresPorFat * bootSector.bytesSector);
	 memset(fat, '\0', bootSector.sectoresPorFat * bootSector.bytesSector);
	 fread(fat, sizeof(char), (bootSector.sectoresPorFat * bootSector.bytesSector), fp);
	 memcpy(*tablaFat, fat, (bootSector.sectoresPorFat * bootSector.bytesSector));
	 fclose(fp);
	 return 0;*/

	/*printf("--------------------leerSegundaFat--------------------\n");
	 int8_t error = 0;
	 uint32_t sectoresFat = bootSector.sectoresPorFat;
	 div_t division = div(sectoresFat, 8); //REDONDEO LA TABLA FAT PARA ARRIBA PARA PEDIR POR CLUSTER
	 uint32_t sectoresFatRedondeados;

	 if (division.rem == 0)
	 sectoresFatRedondeados = sectoresFat;
	 else
	 sectoresFatRedondeados = (division.quot + 1) * 8;

	 uint32_t* tablaFatAux = (uint32_t*) malloc(sectoresFatRedondeados * bootSector.bytesSector);
	 memset(tablaFatAux, 0, sectoresFatRedondeados * bootSector.bytesSector);
	 uint32_t i;
	 for (i = 0; i < sectoresFatRedondeados - 7 && !error; i += SECTORES_BLOQUE) {
	 uint64_t sectorInicio = bootSector.sectoresReservados + bootSector.sectoresPorFat + i;
	 error = leerBloque(sectorInicio, (char*) tablaFatAux + ((i * bootSector.bytesSector / sizeof(uint32_t))));
	 }
	 if (!error) {
	 (*tablaFat) = (uint32_t*) malloc(sectoresFat * bootSector.bytesSector);
	 memset(*tablaFat, 0, sectoresFat * bootSector.bytesSector);
	 for (i = 0; i < (bootSector.sectoresPorFat * bootSector.bytesSector / sizeof(uint32_t)); i++) {
	 (*tablaFat)[i] = tablaFatAux[i];
	 }
	 }
	 printf("--------------------fin-leerSegundaFat--------------------\n");
	 return error;*/
}

int8_t escribirSegundaTablaFat(uint32_t* tablaFat) {
	if (imprimirDebug) {
		printf("--------------------escribirTablaFat--------------------\n");
	}

	div_t division1 = div((bootSector.sectoresReservados + bootSector.sectoresPorFat) * bootSector.bytesSector, TAMANIO_BLOQUE);
	uint64_t offset = division1.rem;

	uint32_t primerBloqueFat = division1.quot;

	div_t division2 = div((bootSector.sectoresReservados + (bootSector.sectoresPorFat * bootSector.cantidadTablasFat)) * bootSector.bytesSector, TAMANIO_BLOQUE);
	uint32_t ultimoBloqueFat;
	if (division2.rem == 0) {
		ultimoBloqueFat = division2.quot;
	} else {
		ultimoBloqueFat = division2.quot + 1;
	}
	char* contenidoAux = (char*) malloc(TAMANIO_BLOQUE);

	//LEO Y ESCRIBO LOS BLOQUES
	//PRIMER BLOQUE
	uint32_t i = primerBloqueFat;
	uint32_t j;
	uint32_t k;
	memset(contenidoAux, '\0', TAMANIO_BLOQUE);
	int8_t error = leerBloque((i * TAMANIO_BLOQUE / bootSector.bytesSector), contenidoAux);

	if (!error) {
		//SOBREESCRIBO LO NECESARIO
		for (j = offset, k = 0; j < (TAMANIO_BLOQUE - 3); j += 4, k++) {
			memcpy(contenidoAux + j, tablaFat + k, 4);
		}

		//ESCRIBO EL BLOQUE CON LOS DATOS SOBRESCRITOS
		error = escribirBloque((i * TAMANIO_BLOQUE / bootSector.bytesSector), contenidoAux);

		if (!error) {
			//ESCRIBO LOS BLOQUES DEL MEDIO
			for (i = primerBloqueFat + 1, j = 0; i < ultimoBloqueFat && !error; i++, j++) {
				error = escribirBloque((i * TAMANIO_BLOQUE / bootSector.bytesSector), (char*)(tablaFat + ((offset + (j * TAMANIO_BLOQUE)) / sizeof(uint32_t))));
			}

			if(!error) {
				//ESCRIBO EL BLOQUE FINAL
						i = ultimoBloqueFat;
						if(division2.rem == 0) {
							error = escribirBloque((i * TAMANIO_BLOQUE / bootSector.bytesSector), (char*)(tablaFat + ((offset + (j * TAMANIO_BLOQUE)) / sizeof(uint32_t))));

							if(!error) {
								return 0;
							} else {
								//ERROR AL ESCRIBIR EL ULTIMO BLOQUE
						return -6;
					}
				} else {
					memset(contenidoAux, '\0', TAMANIO_BLOQUE);
					error = leerBloque((i * TAMANIO_BLOQUE / bootSector.bytesSector), contenidoAux);
					if(!error) {
						//SOBREESCRIBO LO NECESARIO
						k = ((offset + (j * TAMANIO_BLOQUE)) / sizeof(uint32_t));
						for(j = 0; j < division2.rem - 3; j += 4, k++) {
							memcpy(contenidoAux + j, tablaFat + k, 4);
						}

						//ESCRIBO EL ULTIMO BLOQUE
						error = escribirBloque((i * TAMANIO_BLOQUE / bootSector.bytesSector), contenidoAux);
						if(!error) {
							return 0;
						} else {
							//ERROR AL ESCRIBIR EL ULTIMO BLOQUE
							return -5;
						}
					} else {
						//ERROR AL LEER EL ULTIMO BLOQUE
						return -4;
					}
				}
			} else {
				//ERROR AL ESCRIBIR UNO DE LOS BLOQUES DEL MEDIO
				return -3;
			}
		} else {
			//ERROR AL ESCRIBIR EL PRIMER BLOQUE
			return -2;
		}
	} else {
		//ERROR AL LEER EL PRIMER BLOQUE
		return -1;
	}

	/*FILE* fp;
	 fp = fopen("/home/utn_so/Escritorio/fat32.disk", "r+");
	 fseek(fp, ((bootSector.sectoresReservados + bootSector.sectoresPorFat) * bootSector.bytesSector), SEEK_SET);
	 fwrite(tablaFat, 1, bootSector.sectoresPorFat * bootSector.bytesSector, fp);
	 fclose(fp);
	 printf("--------------------fin-leerTablaFat--------------------\n");
	 return 0;*/

	/*printf("--------------------escribirTablaFat--------------------\n");
	 int8_t error = 0;
	 uint32_t sectoresFat = bootSector.sectoresPorFat;
	 div_t division = div(sectoresFat, 8); //REDONDEO LA TABLA FAT PARA ARRIBA PARA PEDIR POR CLUSTER
	 uint32_t sectoresFatRedondeados;

	 if (division.rem == 0)
	 sectoresFatRedondeados = sectoresFat;
	 else
	 sectoresFatRedondeados = (division.quot + 1) * 8;

	 uint32_t i;
	 for (i = 0; i < sectoresFatRedondeados - 7 && !error; i += SECTORES_BLOQUE) {
	 uint64_t sectorInicio = bootSector.sectoresReservados + bootSector.sectoresPorFat + i;
	 error = escribirBloque(sectorInicio, (char*) tablaFat + ((i * bootSector.bytesSector / sizeof(uint32_t))));
	 }
	 printf("--------------------fin-escribirTablaFat--------------------\n");
	 return error;*/
}

int8_t leerFatRegion(void) {
	int8_t error = 0;
	uint32_t i;
	uint8_t coincide = 1;

	uint32_t* primeraTablaFat = NULL;
	uint32_t* segundaTablaFat = NULL;
	pthread_mutex_lock(&mutexUsandoFat);
	leerTablaFat(&primeraTablaFat);
	leerSegundaTablaFat(&segundaTablaFat);
	pthread_mutex_unlock(&mutexUsandoFat);
	uint32_t finalTabla = (bootSector.sectoresPorFat * bootSector.bytesSector) / sizeof(uint32_t);
	for (i = 0; i < finalTabla && coincide; i++) {
		if (primeraTablaFat[i] == segundaTablaFat[i])
			coincide = 1;
		else
			coincide = 0;
	}
	if (coincide)
		return 0;
	else
		return 1;
}

uint8_t estaOcupadoCluster(uint32_t valor) {
	if (valor != 0)
		return 1;
	else
		return 0;
}

uint32_t cantidadClustersOcupados(void) {
	uint32_t* tablaFat;
	pthread_mutex_lock(&mutexUsandoFat);
	leerTablaFat(&tablaFat);
	pthread_mutex_unlock(&mutexUsandoFat);
	uint32_t finalTabla = (bootSector.sectoresPorFat * bootSector.bytesSector) / sizeof(uint32_t);
	uint32_t i;
	uint32_t clustersOcupados = 0;
	for (i = 0; i < finalTabla; i++) {
		if (estaOcupadoCluster(tablaFat[i]))
			clustersOcupados++;
	}
	return clustersOcupados;
}

uint8_t estaLibreCluster(uint32_t valor) {
	if (valor == 0)
		return 1;
	else
		return 0;
}

uint32_t cantidadClustersLibres(void) {
	uint32_t* tablaFat;
	pthread_mutex_lock(&mutexUsandoFat);
	leerTablaFat(&tablaFat);
	pthread_mutex_unlock(&mutexUsandoFat);
	uint32_t finalTabla = (bootSector.sectoresPorFat * bootSector.bytesSector) / sizeof(uint32_t);
	uint32_t i;
	uint32_t clustersLibres = 0;
	for (i = 0; i < finalTabla; i++) {
		if (estaLibreCluster(tablaFat[i]))
			clustersLibres++;
	}
	return clustersLibres;
}

int8_t habilitarClusters(nodoCluster** cClustersFte, nodoCluster** cClustersFin) {
	uint32_t* tablaFat = (uint32_t*) malloc(bootSector.sectoresPorFat * bootSector.bytesSector);
	memset(tablaFat, 0, bootSector.sectoresPorFat * bootSector.bytesSector);
	pthread_mutex_lock(&mutexUsandoFat);
	int8_t error = leerTablaFat(&tablaFat);
	while (*cClustersFte != NULL && !error) {
		uint32_t numCluster = 0;
		error = desencolarCluster(cClustersFte, cClustersFin, &numCluster);
		if (!error) {
			if ((numCluster >= 2 && numCluster <= 268435439) || (numCluster >= 268435448 && numCluster <= 268435455)) {
				if (imprimirDebug) {
					/**/printf("Habilito el cluster [%d].\n", numCluster);
				}
				tablaFat[numCluster] = 0;
			} else {
				//ESE CLUSTER NO PUEDE SER BORRADO
				error = -1;
			}
		}
	}
	pthread_mutex_unlock(&mutexUsandoFat);
	if (!error) {
		error = actualizarTablaFat(tablaFat);
	}
	return error;
}

//--------------------------------------------------
//MANEJO DE CLUSTERS
//--------------------------------------------------
int8_t leerCluster(uint32_t numCluster, char* contenido) {
	FILE* fp;
	fp = fopen("/home/utn_so/Escritorio/fat32.disk", "r");
	uint32_t inicio = ((bootSector.sectoresReservados + (bootSector.sectoresPorFat * bootSector.cantidadTablasFat) + (numCluster * bootSector.sectoresCluster)) * bootSector.bytesSector);
	if (imprimirDebug) {
		/**/
		printf("Voy a leer a partir del byte [%d]\n", inicio);
	}
	fseek(fp, inicio, SEEK_SET);
	fread(contenido, sizeof(char), (bootSector.sectoresCluster * bootSector.bytesSector), fp);
	fclose(fp);
	if (imprimirDebug) {
		uint32_t i;
		/**/ //for (i = 0; i < 4096; i++) {
		/**///printf("[%d] :: [%d]\n", i, contenido[i]);
		/**///}
	}
	return 0;
}

int8_t tieneSiguienteCluster(uint32_t valor) {
	if ((valor >= 2) && (valor <= 268435439)) {
		return 1;
	}
	return 0;
}
//--------------------------------------------------
//MANEJO DE COLA DE CLUSTERS
//--------------------------------------------------
int8_t encolarCluster(nodoCluster** cClusterFte, nodoCluster** cClusterFin, uint32_t numCluster) {

	nodoCluster *nuevo = (nodoCluster*) malloc(sizeof(nodoCluster));
	memset(nuevo, 0, sizeof(nodoCluster));

	nuevo->numCluster = numCluster;

	nuevo->sig = NULL;

	if ((*cClusterFte) == NULL) {

		*cClusterFte = nuevo;

	} else {
		(*cClusterFin)->sig = nuevo;
	}

	*cClusterFin = nuevo;
	return 0;
}

int8_t obtenerCadenaClusters(uint32_t numCluster, nodoCluster** cClusterFte, nodoCluster** cClusterFin) {

	int8_t error = 0;

	//INSERTO EL CLUSTER EN LA COLA DE CLUSTERS
	uint32_t* tablaFat = NULL;
	pthread_mutex_lock(&mutexUsandoFat);
	error = leerTablaFat(&tablaFat);
	pthread_mutex_unlock(&mutexUsandoFat);
	if (!error) {
		/*uint32_t valor = tablaFat[numCluster];*/
		/**/
		/*printf("tablaFat[%d] vale [%d].\n", numCluster, valor);
		 error = encolarCluster(cClusterFte, cClusterFin, numCluster);*/

		/*if (!error) {
		 //SI TIENE UN CLUSTER SIGUIENTE
		 if (tieneSiguienteCluster(valor)) {
		 //LLAMO DE NUEVO A LA MISMA FUNCION CON EL NUEVO VALOR DE CLUSTER
		 error = obtenerCadenaClusters(valor, cClusterFte, cClusterFin);
		 }
		 }*/

		int8_t fin = 0;
		while (!fin && !error) {
			uint32_t valor = tablaFat[numCluster];
			if (imprimirDebug) {
				/**/
				printf("tablaFat[%d] vale [%d].\n", numCluster, valor);
			}
			error = encolarCluster(cClusterFte, cClusterFin, numCluster);

			if (tieneSiguienteCluster(valor)) {
				numCluster = valor;
			} else {
				fin = 1;
			}
		}
	}
	return error;
}

int8_t desencolarCluster(nodoCluster** cClusterFte, nodoCluster** cClusterFin, uint32_t* numCluster) {

	nodoCluster *aux;

	aux = *cClusterFte;

	*numCluster = aux->numCluster;

	*cClusterFte = (*cClusterFte)->sig;

	if ((*cClusterFte) == NULL) {
		*cClusterFin = NULL;
	}

	free(aux);
	return 0;
}

int8_t desencolarClusterFinal(nodoCluster** cClusterFte, nodoCluster** cClusterFin, uint32_t* numCluster) {
	nodoCluster *aux;
	nodoCluster *aux2;

	if (*cClusterFte != *cClusterFin) {
		aux = *cClusterFte;
		while (aux->sig->sig != NULL) {
			aux = aux->sig;
		}
		*numCluster = aux->sig->numCluster;
		aux2 = aux->sig;
		aux->sig = NULL;
		*cClusterFin = aux;
		free(aux2);
	} else {
		*numCluster = (*cClusterFte)->numCluster;
		free(*cClusterFte);
		*cClusterFte = NULL;
		*cClusterFin = NULL;
	}
	return 0;
}

uint16_t tamanioColaClusters(nodoCluster* cClusterFte, nodoCluster* cClusterFin) {
	uint16_t i = 0;
	nodoCluster* aux;
	aux = cClusterFte;
	if (aux == NULL) {
		return 0;
	} else {
		i++;
		while (aux->sig != NULL) {
			i++;
			aux = aux->sig;
		}
		return i;
	}
}

/*//--------------------------------------------------
 //MANEJO DE COLA DE ARCHIVOS Y DIRECTORIOS
 //--------------------------------------------------

 int8_t obtenerColaDirectorios(t_nodoDirOArch** cDirOArchFte, t_nodoDirOArch** cDirOArchFin, char* path) {
 int8_t error = 0;

 *cDirOArchFte = NULL;
 *cDirOArchFin = NULL;

 uint16_t i = 0;
 uint16_t j = 0;
 int8_t finPath = 0;

 if (path[i] == '/') {
 //SI EMPIEZA CON / LA OMITO
 i++;
 j++;
 }
 while (!finPath) {
 //MIENTRAS NO TERMINE EL PATH
 while (path[i] != '/' && path[i] != '\0') {
 i++;
 }
 if (path[i] == '/') {
 //ENCONTRE UN NOMBRE DE DIRECTORIO
 uint8_t longNombre = i - j;
 uint8_t k = 0;
 char* nombreDir = (char*) malloc(i - j + 1);
 memset(nombreDir, '\0', i - j + 1);
 while (k < longNombre) {
 //COPIO EL NOMBRE DEL DIRECTORIO
 nombreDir[k] = path[j];
 k++;
 j++;
 }
 //AHORA j E i VALEN LO MISMO
 nombreDir[k] = '\0';
 error = encolarDirOArch(cDirOArchFte, cDirOArchFin, nombreDir);

 //AUMENTO j E i PARA PASAR LA /
 j++;
 i++;
 } else{
 //YA NO HAY MAS DIRECTORIOS, TERMINO EN \0
 uint8_t longNombre = i - j;
 finPath = 1;
 if (longNombre > 0) {
 //EL ULTIMO CARACTER DEL PATH NO ES UNA /
 uint8_t k = 0;
 char* nombreArch = (char*) malloc(i - j + 1);
 memset(nombreArch, '\0', i - j + 1);
 while (k < longNombre) {
 //COPIO EL NOMBRE DEL DIRECTORIO
 nombreArch[k] = path[j];
 k++;
 j++;
 }
 //AHORA j E i VALEN LO MISMO
 nombreArch[k] = '\0';
 error = encolarDirOArch(cDirOArchFte, cDirOArchFin, nombreArch);

 return 0;
 }else{
 //EL ULTIMO CARACTER DEL PATH ES UNA /
 return 1;
 }
 }
 }
 }*/

//--------------------------------------------------
//MANEJO DE ARCHIVOS Y DIRECTORIOS
//--------------------------------------------------
void parsearDir(char* path, char** ruta) {

	uint16_t i, k;
	for (i = 0; path[i] != '\0'; i++) {
		if (path[i] == '/') {
			k = i;
		}
	}
	if (k == 0) {
		k = 1;
	}
	if (imprimirDebug) {
		printf("%d\n", k);
	}
	*ruta = (char*) malloc(k + 1);
	memset(*ruta, '\0', k + 1);
	for (i = 0; i < k; i++) {
		(*ruta)[i] = path[i];
	}
	(*ruta)[i] = '\0';
	return;
}

void sacarNombreDeRuta(char* path, char** nombre) {

	uint16_t i, k;
	for (i = 0, k = 0; path[i] != '\0'; i++) {
		if (path[i] == '/') {
			k = i;
		}
	}
	if (imprimirDebug) {
		printf("La longitud del path es [%d] y la ultima barra esta en la posicion [%d].\n", i, k);
	}
	*nombre = (char*) malloc(i - k + 1);
	memset(*nombre, '\0', i - k + 1);
	k++; //ME SALTO LA BARRA
	for (i = k; path[i] != '\0'; i++) {
		(*nombre)[i - k] = path[i];
	}
	(*nombre)[i] = '\0';
}

void parsearNomSinExtension(char* nombre, char** nSinExtension) {
	uint32_t i;
	for (i = 0; ((nombre[i] != '\0') && (nombre[i] != '.')); i++) {
	}
	*nSinExtension = (char*) malloc(i + 1);
	memset(*nSinExtension, '\0', i + 1);
	memcpy(*nSinExtension, nombre, i);
	(*nSinExtension)[i] = '\0';
}

void parsearExtension(char* nombre, char** extension) {
	uint8_t i;
	for (i = 0; nombre[i] != '\0' && nombre[i] != '.'; i++)
		;
	if (nombre[i] == '.') {
		//EL NOMBRE TIENE EXTENSION
		i++;
		uint8_t j;
		for (j = i; nombre[j] != '\0'; j++)
			;
		uint8_t longitudExtension = j - i;
		(*extension) = (char*) malloc(longitudExtension + 1);
		memset(*extension, '\0', longitudExtension + 1);
		for (j = 0; j < longitudExtension; j++) {
			(*extension)[j] = nombre[i + j];
		}
		(*extension)[j] = '\0';
	} else {
		//NO TIENE EXTENSION
		(*extension) = (char*) malloc(1);
		(*extension)[0] = '\0';
	}
}

uint32_t deInfoANumCluster(infoArchivoODirectorio info) {
	return ((info.clusterHighTwoBytes * 256) + info.clusterLowTwoBytes);
}

//--------------------------------------------------
//MANEJO DE PILA DE LONG FILE NAME
//--------------------------------------------------
void apilarLongFileName(nodoLongFileName** pLongFileNameFte, t_longFileName longFileName) {
	nodoLongFileName *aux = (nodoLongFileName*) malloc(sizeof(nodoLongFileName));
	memset(aux, 0, sizeof(nodoLongFileName));
	aux->longFileName = longFileName; //COMPROBAR SI ESTA BIEN
	aux->sig = *pLongFileNameFte;
	*pLongFileNameFte = aux;
}

void desapilarLongFileName(nodoLongFileName** pLongFileNameFte, t_longFileName* longFileName) {
	nodoLongFileName *aux;
	aux = *pLongFileNameFte;
	*pLongFileNameFte = (*pLongFileNameFte)->sig;
	*longFileName = aux->longFileName; //COMPROBAR SI ESTA BIEN
	free(aux);
}

uint8_t tamanioPilaLongFileName(nodoLongFileName* pLongFileNameFte) {
	uint8_t i = 0;
	nodoLongFileName* aux;
	aux = pLongFileNameFte;
	if (aux == NULL) {
		return 0;
	} else {
		i++;
		while (aux->sig != NULL) {
			i++;
		}
		return i;
	}
}

void vaciarPilaLongFileName(nodoLongFileName** pLongFileNameFte) {
	while ((*pLongFileNameFte) != NULL) {
		t_longFileName longFileName;
		desapilarLongFileName(pLongFileNameFte, &longFileName);
	}
}

//--------------------------------------------------
//MANEJO DE LONG FILE NAME
//--------------------------------------------------
void obtenerNombreLongFileName(nodoLongFileName* pLongFileNameFte, char* nombre) {
	nodoLongFileName* aux = pLongFileNameFte;
	uint8_t i;
	uint8_t longNombre = tamanioPilaLongFileName(pLongFileNameFte) * 13;
	char* nombreAux = (char*) malloc(longNombre);
	memset(nombreAux, '\0', longNombre);

	for (i = 0; aux != NULL; i++) {
		//PRIMERA PARTE DEL NOMBRE
		size_t longUTF16 = 5;
		size_t longUTF8 = 0;
		unicode_utf16_to_utf8_inbuffer(aux->longFileName.nameCharacters1, longUTF16, (nombreAux + (i * 13)), &longUTF8);

		//SEGUNDA PARTE DEL NOMBRE
		longUTF16 = 6;
		longUTF8 = 0;
		unicode_utf16_to_utf8_inbuffer(aux->longFileName.nameCharacters2, longUTF16, (nombreAux + (i * 13) + 5), &longUTF8);

		//TERCERA PARTE DEL NOMBRE
		longUTF16 = 2;
		longUTF8 = 0;
		unicode_utf16_to_utf8_inbuffer(aux->longFileName.nameCharacters3, longUTF16, (nombreAux + (i * 13) + 11), &longUTF8);

		if (imprimirDebug) {
			/**/
			printf("Se obtuvo el nombre: [%s]\n", nombreAux);
		}
		aux = aux->sig;
	}

	//HAGO QUE EL NOMBRE NO TENGA MAS DE 13 CARACTERES
	//REVISAR
	for (i = 0; nombreAux[i] != '\0' && i < 13; i++) {
		nombre[i] = nombreAux[i];
	}
}

void guardarLongFileNameEnRegComun(t_longFileName regLFN, t_registroDirectorio* regDir) {
	if (imprimirDebug) {
		/**/printf("Guardo el long file name.\n");
	}

	(*regDir).fileName[0] = regLFN.secuenceNumber;
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regDir).fileName[0]);
	}

	(*regDir).fileName[1] = div(regLFN.nameCharacters1[0], 256).quot;
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regDir).fileName[1]);
	}
	(*regDir).fileName[2] = div(regLFN.nameCharacters1[0], 256).rem;
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regDir).fileName[2]);
	}
	(*regDir).fileName[3] = div(regLFN.nameCharacters1[1], 256).quot;
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regDir).fileName[3]);
	}
	(*regDir).fileName[4] = div(regLFN.nameCharacters1[1], 256).rem;
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regDir).fileName[4]);
	}
	(*regDir).fileName[5] = div(regLFN.nameCharacters1[2], 256).quot;
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regDir).fileName[5]);
	}
	(*regDir).fileName[6] = div(regLFN.nameCharacters1[2], 256).rem;
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regDir).fileName[6]);
	}
	(*regDir).fileName[7] = div(regLFN.nameCharacters1[3], 256).quot;
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regDir).fileName[7]);
	}
	(*regDir).fileExtension[0] = div(regLFN.nameCharacters1[3], 256).rem;
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regDir).fileExtension[0]);
	}
	(*regDir).fileExtension[1] = div(regLFN.nameCharacters1[4], 256).quot;
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regDir).fileExtension[1]);
	}
	(*regDir).fileExtension[2] = div(regLFN.nameCharacters1[4], 256).rem;
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regDir).fileExtension[2]);
	}

	(*regDir).fileAttributes = regLFN.attributes;
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regDir).fileAttributes);
	}

	(*regDir).reserved = regLFN.reserved;
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regDir).reserved);
	}

	(*regDir).createTimeFineResolution = regLFN.checksum;
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regDir).createTimeFineResolution);
	}

	(*regDir).createTime = regLFN.nameCharacters2[0];
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regDir).createTime);
	}
	(*regDir).createDate = regLFN.nameCharacters2[1];
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regDir).createDate);
	}
	(*regDir).lastAccessDate = regLFN.nameCharacters2[2];
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regDir).lastAccessDate);
	}
	(*regDir).high2BytesOfCluster = regLFN.nameCharacters2[3];
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regDir).high2BytesOfCluster);
	}
	(*regDir).lastModifiedTime = regLFN.nameCharacters2[4];
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regDir).lastModifiedTime);
	}
	(*regDir).lastModifiedDate = regLFN.nameCharacters2[5];
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regDir).lastModifiedDate);
	}

	(*regDir).low2BytesOfCluster = regLFN.firstCluster;
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regDir).low2BytesOfCluster);
	}

	(*regDir).fileSize = (regLFN.nameCharacters3[0] * 65536) + regLFN.nameCharacters3[1];
	if (imprimirDebug) {
		/**/printf("[%d]\n", (*regDir).fileSize);
	}
}

void deRegDirALongFileName(t_registroDirectorio regDir, t_longFileName* regLFN) {
	if (imprimirDebug) {
		/**/printf("Paso de registro directorio a long file name.\n");
	}

	(*regLFN).secuenceNumber = (uint8_t) regDir.fileName[0];
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regLFN).secuenceNumber);
	}

	(*regLFN).nameCharacters1[0] = ((uint8_t) regDir.fileName[1]) * 256 + regDir.fileName[2];
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regLFN).nameCharacters1[0]);
	}

	(*regLFN).nameCharacters1[1] = ((uint8_t) regDir.fileName[3]) * 256 + regDir.fileName[4];
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regLFN).nameCharacters1[1]);
	}
	(*regLFN).nameCharacters1[2] = ((uint8_t) regDir.fileName[5]) * 256 + regDir.fileName[6];
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regLFN).nameCharacters1[2]);
	}
	(*regLFN).nameCharacters1[3] = ((uint8_t) regDir.fileName[7]) * 256 + regDir.fileExtension[0];
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regLFN).nameCharacters1[3]);
	}
	(*regLFN).nameCharacters1[4] = ((uint8_t) regDir.fileExtension[1]) * 256 + regDir.fileExtension[2];
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regLFN).nameCharacters1[4]);
	}

	(*regLFN).attributes = regDir.fileAttributes;
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regLFN).attributes);
	}

	(*regLFN).reserved = regDir.reserved;
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regLFN).reserved);
	}

	(*regLFN).checksum = regDir.createTimeFineResolution;
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regLFN).checksum);
	}

	(*regLFN).nameCharacters2[0] = regDir.createTime;
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regLFN).nameCharacters2[0]);
	}
	(*regLFN).nameCharacters2[1] = regDir.createDate;
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regLFN).nameCharacters2[1]);
	}
	(*regLFN).nameCharacters2[2] = regDir.lastAccessDate;
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regLFN).nameCharacters2[2]);
	}
	(*regLFN).nameCharacters2[3] = regDir.high2BytesOfCluster;
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regLFN).nameCharacters2[3]);
	}
	(*regLFN).nameCharacters2[4] = regDir.lastModifiedTime;
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regLFN).nameCharacters2[4]);
	}
	(*regLFN).nameCharacters2[5] = regDir.lastModifiedDate;
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regLFN).nameCharacters2[5]);
	}

	(*regLFN).firstCluster = regDir.low2BytesOfCluster;
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regLFN).firstCluster);
	}

	(*regLFN).nameCharacters3[0] = div(regDir.fileSize, 65536).quot;
	if (imprimirDebug) {
		/**/
		printf("[%d]\n", (*regLFN).nameCharacters3[0]);
	}
	(*regLFN).nameCharacters3[1] = div(regDir.fileSize, 65536).rem;
	if (imprimirDebug) {
		/**/printf("[%d]\n", (*regLFN).nameCharacters3[1]);
	}
}

uint8_t esLongFileName(uint8_t atributos) {
	if (atributos == 15)
		return 1;
	return 0;
}

//--------------------------------------------------
//MANEJO DE ARCHIVOS
//--------------------------------------------------

uint8_t esArchivo(uint8_t atributos) {
	//EL BIT QUE MARCA SI ES UN ARCHIVO ES EL 5
	uint8_t bitArchivo = (atributos / 32) - ((atributos / 64) * 2);
	return bitArchivo;
}

uint8_t puedoEscribir(uint8_t atributos) { //libFS.c
	if (((div(atributos, 2)).rem == 0) && atributos != 15) {
		return 1;
	} else {
		return 0;
	}
}

//--------------------------------------------------
//MANEJO DE DIRECTORIOS
//--------------------------------------------------

uint8_t esSubdirectorio(uint8_t atributos) {
	//EL BIT QUE MARCA SI ES UN ARCHIVO ES EL 4
	uint8_t bitArchivo = (atributos / 16) - ((atributos / 32) * 2);
	return bitArchivo;
}

int8_t leerDirectorio(nodoCluster** cClusterFte, nodoCluster** cClusterFin, t_registroDirectorio** tablaDirectorio) {
	int8_t error = 0;
	uint16_t tamanioCluster = bootSector.sectoresCluster * bootSector.bytesSector;
	uint32_t tamanioMaximo = tamanioColaClusters(*cClusterFte, *cClusterFin) * tamanioCluster;
	uint8_t ordenCluster = 0;

	char* contenidoClusters = (char*) malloc(tamanioMaximo);
	memset(contenidoClusters, '\0', tamanioMaximo);

	//RECORRO LOS CLUSTERS CORRESPONDIENTES AL DIRECTORIO
	while (*cClusterFte != NULL) {
		//OBTENGO EL NUMERO DE CLUSTER A LEER
		uint32_t numCluster;
		desencolarCluster(cClusterFte, cClusterFin, &numCluster);

		if (imprimirDebug) {
			printf("Tengo que leer el cluster [%d].\n", numCluster);
		}

		if (numCluster > 1) {
			//LEO EL CONTENIDO DEL CLUSTER
			error = leerCluster(numCluster, (contenidoClusters + (ordenCluster * tamanioCluster)));

			//SI HUBO ERROR
			if (error)
				return error;
		} else {
			return -1;
		}
	}

	//PUEDE HABER UN ERROR MAS ADELANTE SI OCUPA JUSTO X CANTIDAD DE CLUSTERS Y NO ESTA EL REGISTRO VACIO

	//GUARDO EL CONTENIDO DEL DIRECTORIO
	(*tablaDirectorio) = (t_registroDirectorio*) malloc(tamanioMaximo);
	memset(*tablaDirectorio, 0, tamanioMaximo);
	uint32_t cantReg = tamanioMaximo / sizeof(t_registroDirectorio);
	uint32_t i;
	for (i = 0; i < cantReg; i++) {
		(*tablaDirectorio)[i].fileName[0] = contenidoClusters[(i * sizeof(t_registroDirectorio)) + 0];
		(*tablaDirectorio)[i].fileName[1] = contenidoClusters[(i * sizeof(t_registroDirectorio)) + 1];
		(*tablaDirectorio)[i].fileName[2] = contenidoClusters[(i * sizeof(t_registroDirectorio)) + 2];
		(*tablaDirectorio)[i].fileName[3] = contenidoClusters[(i * sizeof(t_registroDirectorio)) + 3];
		(*tablaDirectorio)[i].fileName[4] = contenidoClusters[(i * sizeof(t_registroDirectorio)) + 4];
		(*tablaDirectorio)[i].fileName[5] = contenidoClusters[(i * sizeof(t_registroDirectorio)) + 5];
		(*tablaDirectorio)[i].fileName[6] = contenidoClusters[(i * sizeof(t_registroDirectorio)) + 6];
		(*tablaDirectorio)[i].fileName[7] = contenidoClusters[(i * sizeof(t_registroDirectorio)) + 7];

		(*tablaDirectorio)[i].fileExtension[0] = contenidoClusters[(i * sizeof(t_registroDirectorio)) + 8];
		(*tablaDirectorio)[i].fileExtension[1] = contenidoClusters[(i * sizeof(t_registroDirectorio)) + 9];
		(*tablaDirectorio)[i].fileExtension[2] = contenidoClusters[(i * sizeof(t_registroDirectorio)) + 10];

		(*tablaDirectorio)[i].fileAttributes = contenidoClusters[(i * sizeof(t_registroDirectorio)) + 11];

		(*tablaDirectorio)[i].reserved = contenidoClusters[(i * sizeof(t_registroDirectorio)) + 12];

		(*tablaDirectorio)[i].createTimeFineResolution = contenidoClusters[(i * sizeof(t_registroDirectorio)) + 13];

		(*tablaDirectorio)[i].createTime = (((uint8_t) contenidoClusters[(i * sizeof(t_registroDirectorio)) + 14]) * 256) + ((uint8_t) contenidoClusters[(i * sizeof(t_registroDirectorio)) + 15]);

		(*tablaDirectorio)[i].createDate = (((uint8_t) contenidoClusters[(i * sizeof(t_registroDirectorio)) + 16]) * 256) + ((uint8_t) contenidoClusters[(i * sizeof(t_registroDirectorio)) + 17]);

		(*tablaDirectorio)[i].lastAccessDate = (((uint8_t) contenidoClusters[(i * sizeof(t_registroDirectorio)) + 18]) * 256) + ((uint8_t) contenidoClusters[(i * sizeof(t_registroDirectorio)) + 19]);

		(*tablaDirectorio)[i].high2BytesOfCluster = (((uint8_t) contenidoClusters[(i * sizeof(t_registroDirectorio)) + 20]) * 256) + ((uint8_t) contenidoClusters[(i * sizeof(t_registroDirectorio)) + 21]);

		(*tablaDirectorio)[i].lastModifiedTime = (((uint8_t) contenidoClusters[(i * sizeof(t_registroDirectorio)) + 22]) * 256) + ((uint8_t) contenidoClusters[(i * sizeof(t_registroDirectorio)) + 23]);

		(*tablaDirectorio)[i].lastModifiedDate = (((uint8_t) contenidoClusters[(i * sizeof(t_registroDirectorio)) + 24]) * 256) + ((uint8_t) contenidoClusters[(i * sizeof(t_registroDirectorio)) + 25]);

		(*tablaDirectorio)[i].low2BytesOfCluster = (((uint8_t) contenidoClusters[(i * sizeof(t_registroDirectorio)) + 26]) * 256) + ((uint8_t) contenidoClusters[(i * sizeof(t_registroDirectorio)) + 27]);

		(*tablaDirectorio)[i].fileSize = (((uint8_t) contenidoClusters[(i * sizeof(t_registroDirectorio)) + 28]) * 16777216) + (((uint8_t) contenidoClusters[(i * sizeof(t_registroDirectorio)) + 29]) * 65536) + (((uint8_t) contenidoClusters[(i * sizeof(t_registroDirectorio)) + 30]) * 256) + ((uint8_t) contenidoClusters[(i * sizeof(t_registroDirectorio)) + 31]);
	}
	free(contenidoClusters);
	return 0;
}

int64_t buscarEnDirectorio(t_registroDirectorio* tablaDirectorio, infoArchivoODirectorio* info, uint16_t cantRegistrosDirectorio) {
	if (imprimirDebug) {
		/**/printf("Busco en el directorio el nombre");
		/**/
		printf("[%s", (*info).name);
		/**/
		printf("] y la extension [%s", (*info).extension);
		/**/
		printf("].\n");
	}

	uint32_t i = 0;
	uint8_t encontrado = 0;

	while ((tablaDirectorio[i].fileName[0] != '\0') && i < cantRegistrosDirectorio && !encontrado) {
		if (imprimirDebug) {
			/**/printf("Leo el registro [%d].\n", i);
		}
		if (esArchivo(tablaDirectorio[i].fileAttributes) || esSubdirectorio(tablaDirectorio[i].fileAttributes)) {
			//SI ES UN ARCHIVO O UN SUBDIRECTORIO
			if (imprimirDebug) {
				/**/printf("El registro [%d] contiene un archivo o subdirectorio.\n", i);
			}
			uint8_t j = 0;
			encontrado = 1;

			//COMPARO LOS NOMBRES
			while (j < 13 && (*info).name[j] != '\0' && tablaDirectorio[i].fileName[j] != '\0' && encontrado) {
				encontrado = 1;
				if (tablaDirectorio[i].fileName[j] == (*info).name[j]) {
					if (imprimirDebug) {
						/**/printf("El caracter [%d] del nombre coincide.\n", j);
					}
					encontrado = 1;
				} else {
					if (imprimirDebug) {
						/**/printf("El caracter [%d] del nombre no coincide.\n", j);
					}
					encontrado = 0;
				}
				j++;
			}

			if (encontrado) {
				//SI POR AHORA COINCIDEN
				if (j < 8 && (*info).name[j] == '\0' && tablaDirectorio[i].fileName[j] == '\0') {
					if (imprimirDebug) {
						/**/printf("Ambos nombres terminaron y coinciden, en el registro [%d].\n", i);
					}
					encontrado = 1;
				} else if (j == 8 && (*info).name[j] == '\0') {
					if (imprimirDebug) {
						/**/printf("Los 8 caracteres del nombre coinciden, en el registro [%d].\n", i);
					}
					encontrado = 1;
				} else {
					if (imprimirDebug) {
						/**/printf("Los nombres no coinciden.\n");
					}
					encontrado = 0;
				}

				//SI POR AHORA COINCIDEN
				if (encontrado) {
					//COMPARO LAS EXTENSIONES
					j = 0;
					while (j < 3 && (*info).extension[j] != '\0' && tablaDirectorio[i].fileExtension[j] != '\0' && encontrado) {
						encontrado = 1;
						if (tablaDirectorio[i].fileExtension[j] == (*info).extension[j]) {
							if (imprimirDebug) {
								/**/printf("El caracter [%d] de la extension coincide.\n", j);
							}
							encontrado = 1;
						} else {
							if (imprimirDebug) {
								/**/printf("El caracter [%d] de la extension no coincide.\n", j);
							}
							encontrado = 0;
						}
						j++;
					}

					if (encontrado) {
						//SI POR AHORA COINCIDEN
						if (j < 3 && (*info).extension[j] == '\0' && tablaDirectorio[i].fileExtension[j] == '\0') {
							if (imprimirDebug) {
								/**/printf("Ambas extensiones terminaron y coinciden, en el registro [%d].\n", i);
							}
							encontrado = 1;
						} else if (j == 3 && (*info).extension[j] == '\0') {
							if (imprimirDebug) {
								/**/printf("Los 3 caracteres de la extension coinciden, en el registro [%d].\n", i);
							}
							encontrado = 1;
						} else {
							if (imprimirDebug) {
								/**/printf("Las extensiones no coinciden.\n");
							}
							encontrado = 0;
						}
					}
				}
			}
			if (!encontrado) {
				if (imprimirDebug) {
					/**/printf("No se encontro el registro buscado en el registro [%d].\n", i);
				}
				i++;
			}
		} else if (esLongFileName(tablaDirectorio[i].fileAttributes)) {
			//SI ES UN LONG FILE NAME
			if (imprimirDebug) {
				/**/printf("El registro [%d] contiene un long file name.\n", i);
			}

			//APILO LOS REGISTROS CORRESPONDIENTES
			nodoLongFileName* pLongFileNameFte = NULL;
			while (esLongFileName(tablaDirectorio[i].fileAttributes)) {
				t_longFileName longFileName;
				deRegDirALongFileName(tablaDirectorio[i], &longFileName);
				apilarLongFileName(&pLongFileNameFte, longFileName);
				i++;
			}

			//OBTENGO EL NOMBRE
			char nombre[13];
			obtenerNombreLongFileName(pLongFileNameFte, nombre);

			//COMPARO LOS NOMBRES
			uint8_t j = 0;
			encontrado = 1;
			while (j < 13 && nombre[j] != '\0' && (*info).name[j] != '\0' && nombre[j] != '.' && encontrado) {
				encontrado = 1;
				if (nombre[j] == (*info).name[j]) {
					if (imprimirDebug) {
						/**/printf("El caracter [%d] del nombre coincide.\n", j);
					}
					encontrado = 1;
				} else {
					if (imprimirDebug) {
						/**/printf("El caracter [%d] del nombre no coincide.\n", j);
					}
					encontrado = 0;
				}
				j++;
			}

			//SI POR AHORA COINCIDEN
			if (encontrado) {
				//SI TERMINARON AMBOS NOMBRES
				if (j < 13 && nombre[j] == '\0' && (*info).name[j] == '\0') {
					if (imprimirDebug) {
						/**/printf("Ambos nombres terminaron y coinciden, en el registro [%d].\n", i);
					}
					encontrado = 1;
				} else if (j == 13) {
					if (imprimirDebug) {
						/**/printf("Los 13 caracteres del nombre coinciden, en el registro [%d].\n", i);
					}
					encontrado = 1;
				} else if (j < 13 && nombre[j] == '.') {
					//SI NO TERMINARON COMPARO LAS EXTENSIONES
					if (imprimirDebug) {
						printf("El nombre tiene extension, la comparo.\n");
					}
					j++;
					uint8_t k = 0;
					while (k < 13 && j < 13 && nombre[j] != '\0' && (*info).extension[k] != '\0' && encontrado) {
						encontrado = 1;
						if (nombre[j] == (*info).extension[k]) {
							if (imprimirDebug) {
								/**/printf("El caracter [%d] de la extension coincide.\n", k);
							}
							encontrado = 1;
						} else {
							if (imprimirDebug) {
								/**/printf("El caracter [%d] de la extension no coincide.\n", k);
							}
							encontrado = 0;
						}
						k++;
						j++;
					}

					//SI POR AHORA COINCIDEN
					if (encontrado) {
						if (k < 13 && nombre[j] == '\0' && (*info).extension[k] == '\0') {
							if (imprimirDebug) {
								/**/printf("Ambas extensiones terminaron y coinciden, en el registro [%d].\n", i);
							}
							encontrado = 1;
						} else if (k == 13) {
							if (imprimirDebug) {
								/**/printf("Los 13 caracteres de la extension coinciden, en el registro [%d].\n", i);
							}
							encontrado = 1;
						} else {
							if (imprimirDebug) {
								/**/printf("La extension no coincide.\n");
							}
							encontrado = 0;
						}
					}
				} else {
					if (imprimirDebug) {
						/**/printf("El nombre no coincide.\n");
					}
					encontrado = 0;
				}
			}

			if (imprimirDebug) {
				/**/
				printf("Vacio la pila de long file name.\n");
			}
			vaciarPilaLongFileName(&pLongFileNameFte);

			if (!encontrado) {
				if (imprimirDebug) {
					/**/printf("No se encontro, voy a buscar el siguiente registro.\n");
				}
				i++;
			}

		}

		//NO ES NINGUNO DE LOS ANTERIORES
		else
			i++;
	}

	//SI SE ENCONTRO
	if (encontrado) {
		//COPIO LOS ATRIBUTOS
		if (imprimirDebug) {
			/**/printf("Copio los atributos del registro [%d].\n", i);
		}
		(*info).attributes = tablaDirectorio[i].fileAttributes;
		(*info).reserved = tablaDirectorio[i].reserved;
		(*info).createTimeFineResolution = tablaDirectorio[i].createTimeFineResolution;
		(*info).createTime = tablaDirectorio[i].createTime;
		(*info).createDate = tablaDirectorio[i].createDate;
		(*info).lastAccessDate = tablaDirectorio[i].lastAccessDate;
		(*info).clusterHighTwoBytes = tablaDirectorio[i].high2BytesOfCluster;
		(*info).lastModifiedTime = tablaDirectorio[i].lastModifiedTime;
		(*info).lastModifiedDate = tablaDirectorio[i].lastModifiedDate;
		(*info).clusterLowTwoBytes = tablaDirectorio[i].low2BytesOfCluster;
		(*info).size = tablaDirectorio[i].fileSize;
		return i;
	} else
		return -1;
}

int64_t buscarYModificarDirectorio(t_registroDirectorio* tablaDirectorio, infoArchivoODirectorio* info, uint16_t cantRegistrosDirectorio) {
	uint32_t tamanio = (*info).size;
	int64_t resBusqueda = buscarEnDirectorio(tablaDirectorio, info, cantRegistrosDirectorio);
	if (imprimirDebug) {
		/**/
		printf("Resultado de la busqueda: [%d].\n", resBusqueda);
	}
	if (resBusqueda >= 0) {
		if (imprimirDebug) {
			/**/printf("Encontre el registro a modificar.\n");
		}
		uint32_t numCluster = deInfoANumCluster(*info);
		tablaDirectorio[resBusqueda].fileSize = tamanio;

		if (tamanio == 0 && numCluster > 1) {
			if (imprimirDebug) {
				/**/printf("Tengo que habilitar todos los clusters del archivo para truncarlo a 0.\n");
			}
			tablaDirectorio[resBusqueda].high2BytesOfCluster = 0;
			(*info).clusterHighTwoBytes = 0;
			tablaDirectorio[resBusqueda].low2BytesOfCluster = 0;
			(*info).clusterLowTwoBytes = 0;

			nodoCluster* cClusterFte = NULL;
			nodoCluster* cClusterFin = NULL;
			int8_t error = obtenerCadenaClusters(numCluster, &cClusterFte, &cClusterFin);

			if (!error) {
				if (imprimirDebug) {
					/**/printf("Habilito los clusters.\n");
				}
				error = habilitarClusters(&cClusterFte, &cClusterFin);
				if (error) {
					if (imprimirDebug) {
						/**/printf("Error al habilitar los clusters.\n");
					}
					return 0;
				}
			} else {
				if (imprimirDebug) {
					/**/printf("Error al obtener la cadena de clusters.\n");
				}
				return 0;
			}
		} else if (numCluster == 0 && tamanio > 0) {
			if (imprimirDebug) {
				/**/printf("Tengo que obtener un cluster libre para el comienzo del archivo.\n");
			}
			uint32_t numClusterLibre = obtenerClusterLibre();

			if (numClusterLibre > 1) {
				if (imprimirDebug) {
					/**/printf("Obtube el cluster [%d].\n", numClusterLibre);
				}
				tablaDirectorio[resBusqueda].high2BytesOfCluster = div(numClusterLibre, 65536).quot;
				(*info).clusterHighTwoBytes = div(numClusterLibre, 65536).quot;
				tablaDirectorio[resBusqueda].low2BytesOfCluster = div(numClusterLibre, 65536).rem;
				(*info).clusterLowTwoBytes = div(numClusterLibre, 65536).rem;
			} else {
				if (imprimirDebug) {
					/**/printf("Error al obtener un cluster libre.\n");
				}
				return 0;
			}
		}
	}
	return resBusqueda;
}

int8_t borrarFilaDirectorio(t_registroDirectorio* tablaDirectorio, infoArchivoODirectorio* info, uint16_t cantRegistrosDirectorio) {
	/*int64_t resBusqueda = buscarEnDirectorio(tablaDirectorio, info, cantRegistrosDirectorio);
	 if (resBusqueda >= 0) {
	 tablaDirectorio[resBusqueda].fileName[0] = 229;
	 tablaDirectorio[resBusqueda].fileSize = 0;
	 tablaDirectorio[resBusqueda].high2BytesOfCluster = 0;
	 tablaDirectorio[resBusqueda].low2BytesOfCluster = 0;
	 return 0;
	 } else {
	 return -1;
	 }*/
	uint32_t i = 0;
	uint8_t encontrado = 0;

	if (imprimirDebug) {
		/**/
		printf("Busco en el directorio el nombre [%s] y la extension [%s].\n", (*info).name, (*info).extension);
	}

	while ((tablaDirectorio[i].fileName[0] != '\0') && i < cantRegistrosDirectorio && !encontrado) {
		if (imprimirDebug) {
			/**/printf("Leo el registro [%d].\n", i);
		}
		if (tablaDirectorio[i].fileName[0] != 229) {
			//EL DIRECTORIO NO FUE BORRADO
			if (esArchivo(tablaDirectorio[i].fileAttributes) || esSubdirectorio(tablaDirectorio[i].fileAttributes)) {
				//SI ES UN ARCHIVO O UN SUBDIRECTORIO
				if (imprimirDebug) {
					/**/printf("El registro [%d] contiene un archivo o subdirectorio.\n", i);
				}
				uint8_t j = 0;
				encontrado = 1;

				//COMPARO LOS NOMBRES
				while (j < 13 && (*info).name[j] != '\0' && tablaDirectorio[i].fileName[j] != '\0' && encontrado) {
					encontrado = 1;
					if (tablaDirectorio[i].fileName[j] == (*info).name[j]) {
						if (imprimirDebug) {
							/**/printf("El caracter [%d] del nombre coincide.\n", j);
						}
						encontrado = 1;
					} else {
						if (imprimirDebug) {
							/**/printf("El caracter [%d] del nombre no coincide.\n", j);
						}
						encontrado = 0;
					}
					j++;
				}

				if (encontrado) {
					//SI POR AHORA COINCIDEN
					if (j < 8 && (*info).name[j] == '\0' && tablaDirectorio[i].fileName[j] == '\0') {
						if (imprimirDebug) {
							/**/printf("Ambos nombres terminaron y coinciden, en el registro [%d].\n", i);
						}
						encontrado = 1;
					} else if (j == 8 && (*info).name[j] == '\0') {
						if (imprimirDebug) {
							/**/printf("Los 8 caracteres del nombre coinciden, en el registro [%d].\n", i);
						}
						encontrado = 1;
					} else {
						if (imprimirDebug) {
							/**/printf("Los nombres no coinciden.\n");
						}
						encontrado = 0;
					}

					//SI POR AHORA COINCIDEN
					if (encontrado) {
						//COMPARO LAS EXTENSIONES
						j = 0;
						while (j < 3 && (*info).extension[j] != '\0' && tablaDirectorio[i].fileExtension[j] != '\0' && encontrado) {
							encontrado = 1;
							if (tablaDirectorio[i].fileExtension[j] == (*info).extension[j]) {
								if (imprimirDebug) {
									/**/printf("El caracter [%d] de la extension coincide.\n", j);
								}
								encontrado = 1;
							} else {
								if (imprimirDebug) {
									/**/printf("El caracter [%d] de la extension no coincide.\n", j);
								}
								encontrado = 0;
							}
							j++;
						}

						if (encontrado) {
							//SI POR AHORA COINCIDEN
							if (j < 3 && (*info).extension[j] == '\0' && tablaDirectorio[i].fileExtension[j] == '\0') {
								if (imprimirDebug) {
									/**/printf("Ambas extensiones terminaron y coinciden, en el registro [%d].\n", i);
								}
								encontrado = 1;
								memset(&(tablaDirectorio[i]), 0, sizeof(t_registroDirectorio));
								tablaDirectorio[i].fileName[0] = 229;
							} else if (j == 3 && (*info).extension[j] == '\0') {
								if (imprimirDebug) {
									/**/printf("Los 3 caracteres de la extension coinciden, en el registro [%d].\n", i);
								}
								encontrado = 1;
								memset(&(tablaDirectorio[i]), 0, sizeof(t_registroDirectorio));
								tablaDirectorio[i].fileName[0] = 229;
							} else {
								if (imprimirDebug) {
									/**/printf("Las extensiones no coinciden.\n");
								}
								encontrado = 0;
							}
						}
					}
				}
				if (!encontrado) {
					if (imprimirDebug) {
						/**/printf("No se encontro el registro buscado en el registro [%d].\n", i);
					}
					i++;
				}
			} else if (esLongFileName(tablaDirectorio[i].fileAttributes)) {
				//SI ES UN LONG FILE NAME
				if (imprimirDebug) {
					/**/printf("El registro [%d] contiene un long file name.\n", i);
				}

				//APILO LOS REGISTROS CORRESPONDIENTES
				nodoLongFileName* pLongFileNameFte = NULL;
				while (esLongFileName(tablaDirectorio[i].fileAttributes)) {
					t_longFileName longFileName;
					deRegDirALongFileName(tablaDirectorio[i], &longFileName);
					apilarLongFileName(&pLongFileNameFte, longFileName);
					i++;
				}

				//OBTENGO EL NOMBRE
				char nombre[13];
				obtenerNombreLongFileName(pLongFileNameFte, nombre);

				//COMPARO LOS NOMBRES
				uint8_t j = 0;
				encontrado = 1;
				while (j < 13 && nombre[j] != '\0' && (*info).name[j] != '\0' && nombre[j] != '.' && encontrado) {
					encontrado = 1;
					if (nombre[j] == (*info).name[j]) {
						if (imprimirDebug) {
							/**/printf("El caracter [%d] del nombre coincide.\n", j);
						}
						encontrado = 1;
					} else {
						if (imprimirDebug) {
							/**/printf("El caracter [%d] del nombre no coincide.\n", j);
						}
						encontrado = 0;
					}
					j++;
				}

				//SI POR AHORA COINCIDEN
				if (encontrado) {
					//SI TERMINARON AMBOS NOMBRES
					if (j < 13 && nombre[j] == '\0' && (*info).name[j] == '\0') {
						if (imprimirDebug) {
							/**/printf("Ambos nombres terminaron y coinciden, en el registro [%d].\n", i);
						}
						encontrado = 1;
						memset(&(tablaDirectorio[i]), 0, sizeof(t_registroDirectorio));
						tablaDirectorio[i].fileName[0] = 229;
						uint32_t k;
						for (k = (i - 1); esLongFileName(tablaDirectorio[i].fileAttributes); k--) {
							memset(&(tablaDirectorio[k]), 0, sizeof(t_registroDirectorio));
							tablaDirectorio[k].fileName[0] = 229;
						}
					} else if (j == 13) {
						if (imprimirDebug) {
							/**/printf("Los 13 caracteres del nombre coinciden, en el registro [%d].\n", i);
						}
						encontrado = 1;
						memset(&(tablaDirectorio[i]), 0, sizeof(t_registroDirectorio));
						tablaDirectorio[i].fileName[0] = 229;
						uint32_t k;
						for (k = (i - 1); esLongFileName(tablaDirectorio[k].fileAttributes); k--) {
							memset(&(tablaDirectorio[k]), 0, sizeof(t_registroDirectorio));
							tablaDirectorio[k].fileName[0] = 229;
						}
					} else if (j < 13 && nombre[j] == '.') {
						//SI NO TERMINARON COMPARO LAS EXTENSIONES
						if (imprimirDebug) {
							printf("El nombre tiene extension, la comparo.\n");
						}
						j++;
						uint8_t k = 0;
						while (k < 13 && j < 13 && nombre[j] != '\0' && (*info).extension[k] != '\0' && encontrado) {
							encontrado = 1;
							if (nombre[j] == (*info).extension[k]) {
								if (imprimirDebug) {
									/**/printf("El caracter [%d] de la extension coincide.\n", k);
								}
								encontrado = 1;
							} else {
								if (imprimirDebug) {
									/**/printf("El caracter [%d] de la extension no coincide.\n", k);
								}
								encontrado = 0;
							}
							k++;
							j++;
						}

						//SI POR AHORA COINCIDEN
						if (encontrado) {
							if (k < 13 && nombre[j] == '\0' && (*info).extension[k] == '\0') {
								if (imprimirDebug) {
									/**/printf("Ambas extensiones terminaron y coinciden, en el registro [%d].\n", i);
								}
								encontrado = 1;
								memset(&(tablaDirectorio[i]), 0, sizeof(t_registroDirectorio));
								tablaDirectorio[i].fileName[0] = 229;
								uint32_t l;
								for (l = (i - 1); esLongFileName(tablaDirectorio[l].fileAttributes); l--) {
									memset(&(tablaDirectorio[l]), 0, sizeof(t_registroDirectorio));
									tablaDirectorio[l].fileName[0] = 229;
								}
							} else if (k == 13) {
								if (imprimirDebug) {
									/**/printf("Los 13 caracteres de la extension coinciden, en el registro [%d].\n", i);
								}
								encontrado = 1;
								memset(&(tablaDirectorio[i]), 0, sizeof(t_registroDirectorio));
								tablaDirectorio[i].fileName[0] = 229;
								uint32_t l;
								for (l = (i - 1); esLongFileName(tablaDirectorio[l].fileAttributes); k--) {
									memset(&(tablaDirectorio[l]), 0, sizeof(t_registroDirectorio));
									tablaDirectorio[l].fileName[0] = 229;
								}
							} else {
								if (imprimirDebug) {
									/**/printf("La extension no coincide.\n");
								}
								encontrado = 0;
							}
						}
					} else {
						if (imprimirDebug) {
							/**/printf("El nombre no coincide.\n");
						}
						encontrado = 0;
					}
				}

				if (imprimirDebug) {
					/**/
					printf("Vacio la pila de long file name.\n");
				}
				vaciarPilaLongFileName(&pLongFileNameFte);

				if (!encontrado) {
					if (imprimirDebug) {
						/**/printf("No se encontro, voy a buscar el siguiente registro.\n");
					}
					i++;
				}
			} else {
				//NO ES NINGUNO DE LOS ANTERIORES
				i++;
			}
		} else {
			//EL DIRECTORIO FUE BORRADO
			i++;
		}

	}
	if (encontrado) {
		//COPIO LOS ATRIBUTOS
		(*info).attributes = tablaDirectorio[i].fileAttributes;
		(*info).reserved = tablaDirectorio[i].reserved;
		(*info).createTimeFineResolution = tablaDirectorio[i].createTimeFineResolution;
		(*info).createTime = tablaDirectorio[i].createTime;
		(*info).createDate = tablaDirectorio[i].createDate;
		(*info).lastAccessDate = tablaDirectorio[i].lastAccessDate;
		(*info).clusterHighTwoBytes = tablaDirectorio[i].high2BytesOfCluster;
		(*info).lastModifiedTime = tablaDirectorio[i].lastModifiedTime;
		(*info).lastModifiedDate = tablaDirectorio[i].lastModifiedDate;
		(*info).clusterLowTwoBytes = tablaDirectorio[i].low2BytesOfCluster;
		(*info).size = tablaDirectorio[i].fileSize;
		return 1;
	} else
		return -1;
}

int8_t escribirTablaDirectorio(nodoCluster** cClusterFte, nodoCluster** cClusterFin, t_registroDirectorio* tablaDirectorio) {
	if (imprimirDebug) {
		/**/printf("Entro a escribir el directorio.\n");
	}
	int8_t error = 0;
	while (*cClusterFte != NULL && !error) {
		if (imprimirDebug) {
			/**/printf("Armo un bloque.\n");
		}
		char* contenidoBloque = (char*) malloc(SECTORES_BLOQUE * bootSector.bytesSector);
		memset(contenidoBloque, '\0', SECTORES_BLOQUE * bootSector.bytesSector);
		uint32_t i;
		uint16_t j;
		for (i = 0, j = 0; i < (SECTORES_BLOQUE * bootSector.bytesSector) - 31; i += 32, j++) {
			contenidoBloque[i] = tablaDirectorio[j].fileName[0];
			contenidoBloque[i + 1] = tablaDirectorio[j].fileName[1];
			contenidoBloque[i + 2] = tablaDirectorio[j].fileName[2];
			contenidoBloque[i + 3] = tablaDirectorio[j].fileName[3];
			contenidoBloque[i + 4] = tablaDirectorio[j].fileName[4];
			contenidoBloque[i + 5] = tablaDirectorio[j].fileName[5];
			contenidoBloque[i + 6] = tablaDirectorio[j].fileName[6];
			contenidoBloque[i + 7] = tablaDirectorio[j].fileName[7];
			contenidoBloque[i + 8] = tablaDirectorio[j].fileExtension[0];
			contenidoBloque[i + 9] = tablaDirectorio[j].fileExtension[1];
			contenidoBloque[i + 10] = tablaDirectorio[j].fileExtension[2];
			contenidoBloque[i + 11] = tablaDirectorio[j].fileAttributes;
			contenidoBloque[i + 12] = tablaDirectorio[j].reserved;
			contenidoBloque[i + 13] = tablaDirectorio[j].createTimeFineResolution;
			contenidoBloque[i + 14] = div(tablaDirectorio[j].createTime, 256).quot;
			contenidoBloque[i + 15] = div(tablaDirectorio[j].createTime, 256).rem;
			contenidoBloque[i + 16] = div(tablaDirectorio[j].createDate, 256).quot;
			contenidoBloque[i + 17] = div(tablaDirectorio[j].createDate, 256).rem;
			contenidoBloque[i + 18] = div(tablaDirectorio[j].lastAccessDate, 256).quot;
			contenidoBloque[i + 19] = div(tablaDirectorio[j].lastAccessDate, 256).rem;
			contenidoBloque[i + 20] = div(tablaDirectorio[j].high2BytesOfCluster, 256).quot;
			contenidoBloque[i + 21] = div(tablaDirectorio[j].high2BytesOfCluster, 256).rem;
			contenidoBloque[i + 22] = div(tablaDirectorio[j].lastModifiedTime, 256).quot;
			contenidoBloque[i + 23] = div(tablaDirectorio[j].lastModifiedTime, 256).rem;
			contenidoBloque[i + 24] = div(tablaDirectorio[j].lastModifiedDate, 256).quot;
			contenidoBloque[i + 25] = div(tablaDirectorio[j].lastModifiedDate, 256).rem;
			contenidoBloque[i + 26] = div(tablaDirectorio[j].low2BytesOfCluster, 256).quot;
			contenidoBloque[i + 27] = div(tablaDirectorio[j].low2BytesOfCluster, 256).rem;
			contenidoBloque[i + 28] = div(tablaDirectorio[j].fileSize, 16777216).quot;
			contenidoBloque[i + 29] = div(div(tablaDirectorio[j].fileSize, 16777216).rem, 65536).quot;
			contenidoBloque[i + 30] = div(div(tablaDirectorio[j].fileSize, 65536).rem, 256).quot;
			contenidoBloque[i + 31] = div(tablaDirectorio[j].fileSize, 256).rem;
		}
		/**/
		//printf("Contenido del Bloque:\n");
		/**/
		//for (i = 0; i < SECTORES_BLOQUE * bootSector.bytesSector; i++) {
		/**///printf("[%d]\n", contenidoBloque[i]);
		/**///}
		/**/
		//printf("Fin del Bloque.\n");
		uint32_t numCluster;
		error = desencolarCluster(cClusterFte, cClusterFin, &numCluster);

		if (!error) {
			if (imprimirDebug) {
				/**/printf("Voy a escribir el bloque correspondiente al cluster [%d].\n", numCluster);
			}
			error = escribirBloque(bootSector.sectoresReservados + (bootSector.sectoresPorFat * bootSector.cantidadTablasFat) + (numCluster * bootSector.sectoresCluster), contenidoBloque);
		}
	}
	return error;
}

int8_t mayorCantRegDirConsecutivos(t_registroDirectorio* tablaDir, uint32_t cantRegDir, uint32_t* regInicio, uint32_t* regDisponibles) {
	uint32_t i;
	int8_t error = 0;

//RECORRO TODA LA TABLA DIRECTORIO
	for (i = 0; i < cantRegDir && !error;) {
		if (tablaDir[i].fileName[0] == 0 || tablaDir[i].fileName[0] == 229) {
			//SI EL REGISTRO ESTA DISPONIBLE CUENTO CUANTOS REGISTROS DISPONIBLES HAY CONSECUTIVOS
			if (imprimirDebug) {
				/**/printf("El registro [%d] esta disponible.\n", i);
			}
			uint32_t regInicioAux = i;
			uint32_t regDisponiblesAux = 0;
			for (; (i < cantRegDir) && (tablaDir[i].fileName[0] == 0 || tablaDir[i].fileName[0] == 229); i++) {
				regDisponiblesAux++;
			}

			if (imprimirDebug) {
				/**/
				printf("Hay [%d] registros disponibles consecutivos a partir del registro [%d].\n", regDisponiblesAux, regInicioAux);
			}

			if (regDisponiblesAux > *regDisponibles) {
				//ENCONTRE UNA MAYOR CANTIDAD DE REGISTROS DISPONIBLES
				*regInicio = regInicioAux;
				*regDisponibles = regDisponiblesAux;
			}
		} else {
			//SI EL REGISTRO NO ESTA DISPONIBLE PASO AL SIGUIENTE
			i++;
		}
	}

	return error;
}

//--------------------------------------------------
//MANEJO DE ARCHIVOS Y DIRECTORIOS
//--------------------------------------------------

int8_t buscarInfoPathNoDesdeRaiz(char* path, infoArchivoODirectorio* info) {
	int8_t error = 0;
	char* nombre;
	int8_t k = 0;

//CUENTO EL TAMAÑO DEL NOMBRE
//ARRANCO EN k = 0 PORQUE NO HAY / AL PRINCIPIO
	for (k = 0; (path[k] != '\0') && (path[k] != '/'); k++)
		;

//SI NO HAY MAS PATH
	if (k == 0 && path[k] == '\0') {
		if (imprimirDebug) {
			/**/printf("Se termino el path.\n");
		}
		if (esSubdirectorio((*info).attributes)) {
			return 1;
		} else if (esArchivo((*info).attributes)) {
			return 0;
		}
	}
//SI HAY DOS BARRAS CONSECUTIVAS
	else if (k == 0 && path[k] == '/') {
		if (imprimirDebug) {
			/**/printf("Hay dos barras consecutivas");
		}
		return -1;
	}

//SI NO HUBO ERRORES SIGO

//RESERVO MEMORIA PARA EL NOMBRE DEL SUBDIRECTORIO/ARCHIVO
//RESERVO k + 1 PORQUE AGREGO UN \0 AL FINAL
	nombre = (char*) malloc(k + 1);
	memset(nombre, '\0', k + 1);

//PASO EL NOMBRE DEL DIRECTORIO
//ARRANCO EN k = 0 PORQUE NO HAY / AL PRINCIPIO
	for (k = 0; (path[k] != '\0') && (path[k] != '/'); k++)
		//OBTENGO EL NOMBRE A PARTIR DEL PATH
		nombre[k] = path[k];
	nombre[k] = '\0';

//BUSCO LA CADENA DE CLUSTERS DEL DIRECTORIO ACTUAL
	nodoCluster* cClusterFte = NULL;
	nodoCluster* cClusterFin = NULL;
	uint32_t numCluster = deInfoANumCluster(*info);
	error = obtenerCadenaClusters(numCluster, &cClusterFte, &cClusterFin);

//VACIO LA ESTRUCTURA INFO PARA LLENARLA CON LOS DATOS NUEVOS

	memset(info, 0, sizeof(infoArchivoODirectorio));
	uint8_t j;

//COPIO EL NOMBRE
	for (j = 0; nombre[j] != '\0' && nombre[j] != '.' && j < 13; j++)
		(*info).name[j] = nombre[j];
	if (j < 12)
		(*info).name[j] = '\0';

//SI TIENE EXTENSION LA COPIO
	if (nombre[j] == '.') {
		uint8_t l;
		j++;
		for (l = 0; j < 13 && nombre[j] != '\0'; j++, l++)
			(*info).extension[l] = nombre[j];
		if (l < 13)
			(*info).extension[l] = '\0';
	} else {
		//SI NO TIENE EXTENSION LLENO LA EXTENSION CON \0
		for (j = 0; j < 13; j++)
			(*info).extension[j] = '\0';
	}

//SI NO HUBO ERROR
	if (!error) {
		//LEO EL DIRECTORIO
		t_registroDirectorio* directorio;
		uint16_t cantRegistrosDirectorio = (tamanioColaClusters(cClusterFte, cClusterFin) * bootSector.sectoresCluster * bootSector.bytesSector) / sizeof(t_registroDirectorio);
		error = leerDirectorio(&cClusterFte, &cClusterFin, &directorio);

		//SI NO HUBO ERROR
		if (!error) {
			int64_t resBusqueda = buscarEnDirectorio(directorio, info, cantRegistrosDirectorio);
			free(directorio);

			//SI NO HUBO ERROR
			if (resBusqueda >= 0) {
				if (imprimirDebug) {
					/**/printf("Se encontro [%d].\n", (*info).attributes);
				}
				if ((esSubdirectorio((*info).attributes) && path[k] == '/') || (esSubdirectorio((*info).attributes) && path[k] == '\0') || (esArchivo((*info).attributes) && path[k] == '\0')) {
					//BUSCO DE VUELTA CON EL NUEVO PATH
					//LE AGREGO i + 1 PARA SACAR EL DIRECTORIO DONDE YA BUSQUE Y LA SIGUIENTE BARRA

					int8_t resBusqueda2;

					if (path[k] != '/') {
						resBusqueda2 = buscarInfoPathNoDesdeRaiz(path + k, info);
					} else {
						resBusqueda2 = buscarInfoPathNoDesdeRaiz(path + k + 1, info);
					}

					if (imprimirDebug) {
						/**/printf("Resultado de la busqueda: [%d].\n", resBusqueda2);
					}

					return resBusqueda2;
				} else {
					return -1;
				}
			} else {
				//HUBO ERROR AL BUSCAR EN EL DIRECTORIO
				return error;
			}
		} else {
			//HUBO ERROR AL LEER EL DIRECTORIO
			return error;
		}
	} else {
		//HUBO ERROR AL OBTENER LA CADENA DE CLUSTERS
		return error;
	}
}

int8_t buscarInfoPathDesdeRaiz(char* path, infoArchivoODirectorio* info) {
	int8_t error = 0;

	if (path[0] == '/') {
		int8_t k = 0;

		if (imprimirDebug) {
			/**/
			printf("El path a buscar es: [%s].\n", path);
		}

		//DESCARTO LA PRIMERA PARTE DEL PATH POR SER EL DIRECTORIO RAIZ
		//CONSIDERO UNA RUTA /algo/otro algo/algo.txt
		//O /algo/otro algo/
		//O /algo/otro algo

		if (imprimirDebug) {
			/**/
			printf("El path a buscar (sacando el directorio raiz) es: [%s].\n", path + 1);
		}

		//CUENTO EL TAMAÑO DEL NOMBRE
		for (k = 0; (path[1 + k] != '\0') && (path[1 + k] != '/'); k++) {
			if (imprimirDebug) {
				printf("%c", path[1 + k]);
			}

		}
		if (imprimirDebug) {
			printf("\n");
		}
		if (imprimirDebug) {
			printf("%d\n", k);
		}

		//SI NO HAY MAS PATH, EL ARCHIVO TIENE QUE SER CREADO EN EL DIRECTORIO RAIZ
		if (k == 0 && path[1 + k] == '\0') {
			if (imprimirDebug) {
				/**/printf("Se devolveran los datos del directorio raiz.\n");
			}
			(*info).createTimeFineResolution = 0;
			(*info).createTime = 0;
			(*info).createDate = 0;
			(*info).lastAccessDate = 0;
			(*info).lastModifiedTime = 0;
			(*info).lastModifiedDate = 0;

			nodoCluster* cClusterFte = NULL;
			nodoCluster* cClusterFin = NULL;

			uint32_t cantClusters;
			uint32_t numCluster = deInfoANumCluster(*info);

			if (numCluster > 1) {
				int8_t error = obtenerCadenaClusters(numCluster, &cClusterFte, &cClusterFin);
				if (!error) {
					cantClusters = tamanioColaClusters(cClusterFte, cClusterFin);
					while (cClusterFte != NULL) {
						desencolarCluster(&cClusterFte, &cClusterFin, &numCluster);
					}
				} else {
					return -2;
				}
			} else {
				cantClusters = 0;
			}

			(*info).size = cantClusters * bootSector.sectoresCluster * bootSector.bytesSector;

			return 1;
		} else if (k == 0 && path[1 + k] == '/') {
			//SI HAY DOS BARRAS CONSECUTIVAS
			if (imprimirDebug) {
				/**/printf("Hay dos barras consecutivas.\n");
			}
			return -4;
		}
		//SI NOHUBO ERRORES SIGO
		if (imprimirDebug) {
			/**/
			printf("Voy a buscar el siguiente subdirectorio.\n");
		}
		int8_t resBusqueda = buscarInfoPathNoDesdeRaiz(path + 1, info);

		//SI NO HUBO ERRORES
		if (resBusqueda == 0 || resBusqueda == 1) {
			if (esArchivo((*info).attributes)) {
				//SI LA INFORMACION ENCONTRADA ES DE UN ARCHIVO
				if (imprimirDebug) {
					/**/printf("Se encontro informacion de un archivo.\n");
				}
				return 0;
			} else if (esSubdirectorio((*info).attributes)) {
				if (imprimirDebug) {
					/**/printf("Se encontro informacion de un subdirectorio.\n");
				}
				return 1;
			} else {
				//LA INFORMACION ENCONTRADA NO CORRESPONDE A UN ARCHIVO NI A UN SUBDIRECTORIO
				if (imprimirDebug) {
					/**/printf("No se encontro informacion de un archivo ni un subdirectorio.\n");
				}
				return -3;
			}
		} else {
			//HUBO UN ERROR AL BUSCAR EL PATH
			if (imprimirDebug) {
				/**/printf("Hubo un error al buscar el path.\n");
			}
			return -2;
		}
	} else {
		//NO HAY /
		return -1;
	}
}

//--------------------------------------------------
//MANEJO DE ARCHIVOS
//--------------------------------------------------

int8_t leerContenidoArchivo(nodoCluster** cClusterFte, nodoCluster** cClusterFin, char* contenido, uint32_t tamanio) {
	FILE* fp;
	fp = fopen("/home/utn_so/Escritorio/fat32.disk", "w");
	uint32_t i = 0;
	uint32_t tamanioMaxArch = tamanioColaClusters(*cClusterFte, *cClusterFin) * bootSector.sectoresCluster * bootSector.bytesSector;
	char* contenidoAux = (char*) malloc(tamanioMaxArch);
	memset(contenidoAux, '\0', tamanioMaxArch);
	while ((*cClusterFte) != NULL) {
		uint32_t numCluster;
		if (numCluster > 1) {
			desencolarCluster(cClusterFte, cClusterFin, &numCluster);
			fseek(fp, ((bootSector.sectoresReservados + (bootSector.sectoresPorFat * bootSector.cantidadTablasFat) + (numCluster * bootSector.sectoresCluster)) * bootSector.bytesSector), SEEK_SET);
			uint32_t corrimiento = i * bootSector.sectoresCluster * bootSector.bytesSector;
			fread((contenidoAux + corrimiento), sizeof(char), (bootSector.sectoresCluster * bootSector.bytesSector), fp);} else
			return -1;
		}
	fclose(fp);
	for (i = 0; i < tamanio; i++)
		contenido[i] = contenidoAux[i];
	return 0;
}

int64_t leerArchivo(char* path, char** contenidoArchivo, infoArchivoODirectorio* info, off_t offset, size_t size) {

//BUSCO LA INFORMACION DEL ARCHIVO
	div_t division = div(bootSector.rootDirectoryCluster, 256);
	(*info).clusterHighTwoBytes = division.quot;
	(*info).clusterLowTwoBytes = division.rem;
	(*info).attributes = 16;

	char* ruta;
	parsearDir(path, &ruta);
	int8_t error = buscarInfoPathDesdeRaiz(path, info);

	uint32_t numCluster = deInfoANumCluster(*info);

	if ((*info).size < offset) {
		return 0;
	} else if ((*info).size < offset + size) {
		size = (*info).size - offset;
	}

//SI NO HUBO ERROR
	if (!error) {
		//SI EL NUMERO DE CLUSTER ES CORRECTO
		if (numCluster >= bootSector.rootDirectoryCluster || (((*info).size == 0) && (numCluster == 0))) {
			//OBTENGO DE LA TABLA FAT TODOS LOS CLUSTERS CORRESPONDIENTES A ESE ARCHIVO
			nodoCluster* cClusterFte = NULL;
			nodoCluster* cClusterFin = NULL;
			error = obtenerCadenaClusters(numCluster, &cClusterFte, &cClusterFin);

			//SI NO HUBO ERROR
			if (!error) {

				div_t division2 = div(offset, TAMANIO_BLOQUE);
				uint32_t cantBloquesQNoSeLeen = division2.quot;

				div_t division3 = div(division2.rem + size, TAMANIO_BLOQUE);
				uint32_t cantClustersALeer;
				if (division3.rem == 0) {
					cantClustersALeer = division3.quot;
				} else {
					cantClustersALeer = division3.quot + 1;
				}

				uint32_t i;
				for (i = 0; i < cantBloquesQNoSeLeen; i++) {
					if (cClusterFte != NULL) {
						uint32_t numClusterAux;
						error = desencolarCluster(&cClusterFte, &cClusterFin, &numClusterAux);
					} else {
						return -7;
					}
				}

				while (tamanioColaClusters(cClusterFte, cClusterFin) > cantClustersALeer) {
					uint32_t numClusterAux;
					desencolarClusterFinal(&cClusterFte, &cClusterFin, &numClusterAux);
				}

				if (imprimirDebug) {
					/**/
					printf("Tamanio de la cola de clusters: [%d].\n", tamanioColaClusters(cClusterFte, cClusterFin));
				}

				char* contenidoAux = (char*) malloc(tamanioColaClusters(cClusterFte, cClusterFin) * bootSector.sectoresCluster * bootSector.bytesSector);

				for (i = 0; cClusterFte != NULL && !error; i++) {

					desencolarCluster(&cClusterFte, &cClusterFin, &numCluster);
					uint64_t sectorInicio = bootSector.sectoresReservados + (bootSector.sectoresPorFat * bootSector.cantidadTablasFat) + (numCluster * bootSector.sectoresCluster);

					char* contenidoBloque;
					pthread_mutex_lock(&mutexUsandoCache);
					int8_t estaEnCache = buscarBloqueEnCache(path, (sectorInicio * bootSector.bytesSector / TAMANIO_BLOQUE), &contenidoBloque);
					if (estaEnCache) {
						uint64_t j;
						uint64_t k;
						for (j = i * TAMANIO_BLOQUE, k = 0; k < TAMANIO_BLOQUE; j++, k++) {
							contenidoAux[j] = contenidoBloque[k];
						}
					} else {
						error = leerBloque(sectorInicio, contenidoAux + (i * TAMANIO_BLOQUE));
						if (!error) {
							error = guardarEnCache(path, (sectorInicio * bootSector.bytesSector) / TAMANIO_BLOQUE
							, contenidoAux + (i * TAMANIO_BLOQUE));
							if (error) {
								return error;
							}
						} else {
							return error;
						}
					}
					pthread_mutex_unlock(&mutexUsandoCache);
				}

				//SI NO HUBO ERROR
				if (!error) {
					//GUARDO EL CONTENIDO DEL ARCHIVO
					(*contenidoArchivo) = (char*) malloc(size);
					memset(*contenidoArchivo, '\0', size);

					uint32_t j;
					for (j = 0, i = division2.rem; i < (division2.rem + size); j++, i++) {
						(*contenidoArchivo)[j] = contenidoAux[i];
						if (imprimirDebug) {
							printf("[%d]::[%d].\n", (*contenidoArchivo)[j], contenidoAux[i]);
						}
					}

					//DEVUELVO QUE NO HUBO ERROR
					return size;
				} else {
					//HUBO ERROR AL LEER EL CONTENIDO DEL ARCHIVO
					return error;
				}
			} else {
				//HUBO ERROR AL OBTENER LOS CLUSTERS DEL ARCHIVO
				return error;
			}
		} else {
			//NUMERO DE CLUSTER INCORRECTO
			return -1;
		}
	} else {
		//HUBO ERROR AL BUSCAR EL CLUSTER
		return error;
	}
}

uint16_t obtenerTime() {
	char buffer[3];
	time_t tiempo = time(NULL);
	struct tm* tiempoLocal = localtime(&tiempo);
	memset(buffer, 0, 3);
	strftime(buffer, 3, "%H", tiempoLocal);
	uint8_t hora = atoi(buffer);
	memset(buffer, 0, 3);
	strftime(buffer, 3, "%M", tiempoLocal);
	uint8_t minutos = atoi(buffer);
	memset(buffer, 0, 3);
	strftime(buffer, 3, "%S", tiempoLocal);
	uint8_t segundos = atoi(buffer) / 2;
	return ((hora * potencia(2, 11)) + (minutos * potencia(2, 5)) + segundos);
}

uint16_t obtenerDate() {
	char buffer[5];
	time_t tiempo = time(NULL);
	struct tm* tiempoLocal = localtime(&tiempo);
	memset(buffer, 0, 5);
	strftime(buffer, 5, "%Y", tiempoLocal);
	uint8_t anio = atoi(buffer) - 1980;
	memset(buffer, 0, 5);
	strftime(buffer, 5, "%m", tiempoLocal);
	uint8_t mes = atoi(buffer);
	memset(buffer, 0, 5);
	strftime(buffer, 5, "%d", tiempoLocal);
	uint8_t dia = atoi(buffer) / 2;
	return ((anio * potencia(2, 9)) + (mes * potencia(2, 5)) + dia);
}

//--------------------------------------------------
//MANEJO DE COMANDOS DE LA CONSOLA
//--------------------------------------------------
int8_t esSalir(char* comando) {
	if (strcmp(comando, "salir") == 0)
		return 1;
	else
		return 0;
}

int8_t esFsinfo(char* comando) {
	if (strcmp(comando, "fsinfo") == 0)
		return 1;
	else
		return 0;
}

int8_t esFinfo(char* comando) {
	if (strcmp(comando, "finfo") == 0)
		return 1;
	else
		return 0;
}

int8_t esAyuda(char* comando) {
	if (strcmp(comando, "ayuda") == 0)
		return 1;
	else
		return 0;
}

int8_t esInfoCache(char* comando) {
	if (strcmp(comando, "infocache") == 0)
		return 1;
	else
		return 0;
}

//--------------------------------------------------
//MANEJO DE ARGV
//--------------------------------------------------

int8_t esImprimirDebug(char* argumento) {
	if (strcmp(argumento, "-impr") == 0) {
		printf("Se encontro imprimirDebug [%s].\n", argumento);
		return 1;
	} else {
		return 0;
	}
}

int8_t esNoUsarFuse(char* argumento) {
	if (strcmp(argumento, "-nofuse") == 0) {
		printf("Se encontro noUsarFuse [%s].\n", argumento);
		return 1;
	} else {
		return 0;
	}
}

int8_t esNoUsarSockets(char* argumento) {
	if (strcmp(argumento, "-nosock") == 0) {
		printf("Se encontro noUsarSockets [%s].\n", argumento);
		return 1;
	} else {
		return 0;
	}
}

int8_t esNoUsarPool(char* argumento) {
	if (strcmp(argumento, "-nopool") == 0) {
		printf("Se encontro noUsarPoolConexiones [%s].\n", argumento);
		return 1;
	} else {
		return 0;
	}
}

int8_t esArgumentoPropio(char* argumento) {
	if (esImprimirDebug(argumento) || esNoUsarFuse(argumento) || esNoUsarSockets(argumento) || esNoUsarPool(argumento)) {
		printf("Se encontro un argumento propio [%s].\n", argumento);
		return 1;
	} else {
		return 0;
	}
}

void parsearArgumentoPropio(char* argumento) {
	if (esImprimirDebug(argumento)) {
		printf("imprimirDebug = 1.\n");
		imprimirDebug = 1;
	} else if (esNoUsarFuse(argumento)) {
		printf("usarFUSE = 0.\n");
		usarFUSE = 0;
	} else if (esNoUsarSockets(argumento)) {
		printf("usarSockets = 0.\n");
		usarSockets = 0;
	} else if (esNoUsarPool(argumento)) {
		printf("usarPoolConexiones = 0");
		usarPoolConexiones = 0;
	}
}

void parsearArgV(char*** argv) {
	char** argvAux = NULL;
	uint8_t i, k;
	for (i = 0, k = 0; (*argv)[i]; i++) {
		printf("Entro al for.\n");
		if (!esArgumentoPropio((*argv)[i])) {
			printf("El argumento no es propio [%s].\n", (*argv)[i]);
			k++;
		} else {
			printf("El argumento es propio [%s].\n", (*argv)[i]);
			parsearArgumentoPropio((*argv)[i]);
		}
	}

	k++;
	argvAux = (char**) malloc(k * sizeof(char*));

	for (i = 0; i < k; i++) {
		argvAux[i] = NULL;
	}

	uint8_t j;
	for (i = 0, j = 0; j < k && (*argv)[i]; i++) {
		if (!esArgumentoPropio((*argv)[i])) {
			argvAux[j] = (*argv)[i];
			j++;
		}
	}

	*argv = argvAux;
}
